/**
 * Copyright (c) 2006-2015, JGraph Ltd
 */

/**
 * 注册图形形状。
 * 此文件包含各种图形形状的定义和绘制方法，用于在绘图编辑器中创建不同类型的可视化元素。
 */
(function () {
    // 后续可用于实现条纹效果
    /**
     * 绘制表格背景，支持行列颜色交替显示。
     * 根据表格的行和列结构绘制背景颜色，可以为偶数行/列和奇数行/列设置不同的颜色。
     * 
     * @param {Object} state - 单元格状态对象，包含样式和视图信息
     * @param {Object} c - 画布对象，用于绘制操作
     * @param {number} x - 起始X坐标
     * @param {number} y - 起始Y坐标
     * @param {number} w - 宽度
     * @param {number} h - 高度
     * @param {number} r - 圆角半径
     */
    function paintTableBackground(state, c, x, y, w, h, r) {
        if (state != null) {
            // 获取图形和单元格信息
            var graph = state.view.graph;
            var start = graph.getActualStartSize(state.cell);
            var rows = graph.model.getChildCells(state.cell, true);

            if (rows.length > 0) {
                // 检查是否启用指针事件
                var events = false;

                if (this.style != null) {
                    events = mxUtils.getValue(this.style, mxConstants.STYLE_POINTER_EVENTS, '1') == '1';
                }

                if (!events) {
                    c.pointerEvents = false;
                }

                // 获取行列颜色设置
                var evenRowColor = mxUtils.getValue(state.style,
                    'evenRowColor', mxConstants.NONE);
                var oddRowColor = mxUtils.getValue(state.style,
                    'oddRowColor', mxConstants.NONE);
                var evenColColor = mxUtils.getValue(state.style,
                    'evenColumnColor', mxConstants.NONE);
                var oddColColor = mxUtils.getValue(state.style,
                    'oddColumnColor', mxConstants.NONE);
                var cols = graph.model.getChildCells(rows[0], true);

                // 绘制列背景
                for (var i = 0; i < cols.length; i++) {
                    var clr = (mxUtils.mod(i, 2) == 1) ? evenColColor : oddColColor;
                    var geo = graph.getCellGeometry(cols[i]);

                    if (geo != null && clr != mxConstants.NONE) {
                        c.setFillColor(clr);
                        c.begin();
                        c.moveTo(x + geo.x, y + start.y);

                        if (r > 0 && i == cols.length - 1) {
                            c.lineTo(x + geo.x + geo.width - r, y);
                            c.quadTo(x + geo.x + geo.width, y, x + geo.x + geo.width, y + r);
                            c.lineTo(x + geo.x + geo.width, y + h - r);
                            c.quadTo(x + geo.x + geo.width, y + h, x + geo.x + geo.width - r, y + h);
                        } else {
                            c.lineTo(x + geo.x + geo.width, y + start.y);
                            c.lineTo(x + geo.x + geo.width, y + h - start.height);
                        }

                        c.lineTo(x + geo.x, y + h);
                        c.close();
                        c.fill();
                    }
                }

                // 绘制行背景
                for (var i = 0; i < rows.length; i++) {
                    var clr = (mxUtils.mod(i, 2) == 1) ? evenRowColor : oddRowColor;
                    var geo = graph.getCellGeometry(rows[i]);

                    if (geo != null && clr != mxConstants.NONE) {
                        var b = (i == rows.length - 1) ? y + h : y + geo.y + geo.height;
                        c.setFillColor(clr);

                        c.begin();
                        c.moveTo(x + start.x, y + geo.y);
                        c.lineTo(x + w - start.width, y + geo.y);

                        if (r > 0 && i == rows.length - 1) {
                            c.lineTo(x + w, b - r);
                            c.quadTo(x + w, b, x + w - r, b);
                            c.lineTo(x + r, b);
                            c.quadTo(x, b, x, b - r);
                        } else {
                            c.lineTo(x + w - start.width, b);
                            c.lineTo(x + start.x, b);
                        }

                        c.close();
                        c.fill();
                    }
                }
            }
        }
    };

    // 表格形状
    /**
     * 表格形状构造函数，继承自 mxSwimlane。
     * 用于创建具有行列结构的表格单元格，支持表格样式和布局。
     */
    function TableShape() {
        mxSwimlane.call(this);
    };

    mxUtils.extend(TableShape, mxSwimlane);

    /**
     * 获取表格标签的边界区域。
     * 根据标题大小决定使用基础形状还是泳道形状的标签边界计算方法。
     * 
     * @param {mxRectangle} rect - 形状的矩形区域
     * @returns {mxRectangle} 标签的边界区域
     */
    TableShape.prototype.getLabelBounds = function (rect) {
        var start = this.getTitleSize();

        if (start == 0) {
            return mxShape.prototype.getLabelBounds.apply(this, arguments);
        } else {
            return mxSwimlane.prototype.getLabelBounds.apply(this, arguments);
        }
    };

    /**
     * 绘制表格顶点形状。
     * 根据标题大小选择合适的背景绘制方法，然后绘制前景内容。
     * 
     * @param {Object} c - 画布对象
     * @param {number} x - X坐标
     * @param {number} y - Y坐标
     * @param {number} w - 宽度
     * @param {number} h - 高度
     */
    TableShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        // 后续可拆分背景以添加条纹效果
        //paintTableBackground(this.state, c, x, y, w, h);

        var start = this.getTitleSize();

        if (start == 0) {
            mxRectangleShape.prototype.paintBackground.apply(this, arguments);
        } else {
            mxSwimlane.prototype.paintVertexShape.apply(this, arguments);
            c.translate(-x, -y);
        }

        this.paintForeground(c, x, y, w, h);
    };

    /**
     * 绘制表格前景内容。
     * 处理形状的旋转和翻转变换，然后绘制表格的线条和边框。
     * 
     * @param {Object} c - 画布对象
     * @param {number} x - X坐标
     * @param {number} y - Y坐标
     * @param {number} w - 宽度
     * @param {number} h - 高度
     */
    TableShape.prototype.paintForeground = function (c, x, y, w, h) {
        if (this.state != null) {
            var flipH = this.flipH;
            var flipV = this.flipV;

            if (this.direction == mxConstants.DIRECTION_NORTH || this.direction == mxConstants.DIRECTION_SOUTH) {
                var tmp = flipH;
                flipH = flipV;
                flipV = tmp;
            }

            // 使用负变换避免保存/恢复操作
            c.rotate(-this.getShapeRotation(), flipH, flipV, x + w / 2, y + h / 2);

            s = this.scale;
            x = this.bounds.x / s;
            y = this.bounds.y / s;
            w = this.bounds.width / s;
            h = this.bounds.height / s;
            this.paintTableForeground(c, x, y, w, h);
        }
    };

    /**
     * 绘制表格前景的行列分隔线。
     * 根据样式设置绘制表格的行线和列线，形成网格结构。
     * 
     * @param {Object} c - 画布对象
     * @param {number} x - X坐标
     * @param {number} y - Y坐标
     * @param {number} w - 宽度
     * @param {number} h - 高度
     */
    TableShape.prototype.paintTableForeground = function (c, x, y, w, h) {
        var graph = this.state.view.graph;
        var start = graph.getActualStartSize(this.state.cell);
        var rows = graph.model.getChildCells(this.state.cell, true);

        if (rows.length > 0) {
            var rowLines = mxUtils.getValue(this.state.style,
                'rowLines', '1') != '0';
            var columnLines = mxUtils.getValue(this.state.style,
                'columnLines', '1') != '0';

            // 绘制行分隔线
            if (rowLines) {
                for (var i = 1; i < rows.length; i++) {
                    var geo = graph.getCellGeometry(rows[i]);

                    if (geo != null) {
                        c.begin();
                        c.moveTo(x + start.x, y + geo.y);
                        c.lineTo(x + w - start.width, y + geo.y);
                        c.end();
                        c.stroke();
                    }
                }
            }

            if (columnLines) {
                var cols = graph.model.getChildCells(rows[0], true);

                // 绘制列分隔线
                for (var i = 1; i < cols.length; i++) {
                    var geo = graph.getCellGeometry(cols[i]);

                    if (geo != null) {
                        c.begin();
                        c.moveTo(x + geo.x + start.x, y + start.y);
                        c.lineTo(x + geo.x + start.x, y + h - start.height);
                        c.end();
                        c.stroke();
                    }
                }
            }
        }
    };

    mxCellRenderer.registerShape('table', TableShape);

    // 立方体形状，支持大小样式
    /**
     * 立方体形状构造函数，继承自 mxCylinder。
     * 创建具有3D效果的立方体图形，支持自定义大小和透明度效果。
     */
    function CubeShape() {
        mxCylinder.call(this);
    };
    mxUtils.extend(CubeShape, mxCylinder);
    
    /**
     * 立方体边角的默认大小。
     * 控制3D效果中斜面的大小，默认为20像素。
     */
    CubeShape.prototype.size = 20;
    
    /**
     * 第一层阴影的透明度。
     * 用于创建3D效果的顶面阴影，范围-1到1，默认为0（无阴影）。
     */
    CubeShape.prototype.darkOpacity = 0;
    
    /**
     * 第二层阴影的透明度。
     * 用于创建3D效果的侧面阴影，范围-1到1，默认为0（无阴影）。
     */
    CubeShape.prototype.darkOpacity2 = 0;

    /**
     * 绘制立方体顶点形状。
     * 绘制3D立方体，包括主体和阴影效果，创建立体视觉效果。
     * 
     * @param {Object} c - 画布对象
     * @param {number} x - X坐标
     * @param {number} y - Y坐标  
     * @param {number} w - 宽度
     * @param {number} h - 高度
     */
    CubeShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        // 计算立方体边角大小，确保在合理范围内
        var s = Math.max(0, Math.min(w, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))));
        // 获取阴影透明度设置
        var op = Math.max(-1, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'darkOpacity', this.darkOpacity))));
        var op2 = Math.max(-1, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'darkOpacity2', this.darkOpacity2))));
        c.translate(x, y);

        c.begin();
        c.moveTo(0, 0);
        c.lineTo(w - s, 0);
        c.lineTo(w, s);
        c.lineTo(w, h);
        c.lineTo(s, h);
        c.lineTo(0, h - s);
        c.lineTo(0, 0);
        c.close();
        c.end();
        c.fillAndStroke();

        if (!this.outline) {
            c.setShadow(false);

            if (op != 0) {
                c.setFillAlpha(Math.abs(op));
                c.setFillColor((op < 0) ? '#FFFFFF' : '#000000');
                c.begin();
                c.moveTo(0, 0);
                c.lineTo(w - s, 0);
                c.lineTo(w, s);
                c.lineTo(s, s);
                c.close();
                c.fill();
            }

            if (op2 != 0) {
                c.setFillAlpha(Math.abs(op2));
                c.setFillColor((op2 < 0) ? '#FFFFFF' : '#000000');
                c.begin();
                c.moveTo(0, 0);
                c.lineTo(s, s);
                c.lineTo(s, h);
                c.lineTo(0, h - s);
                c.close();
                c.fill();
            }

            c.begin();
            c.moveTo(s, h);
            c.lineTo(s, s);
            c.lineTo(0, 0);
            c.moveTo(s, s);
            c.lineTo(w, s);
            c.end();
            c.stroke();
        }
    };
    /**
     * 获取立方体标签的边距。
     * 当启用边界标签时，根据立方体的边角大小计算标签的边距偏移。
     * 
     * @param {mxRectangle} rect - 形状的矩形区域
     * @returns {mxRectangle|null} 标签边距或null
     */
    CubeShape.prototype.getLabelMargins = function (rect) {
        if (mxUtils.getValue(this.style, 'boundedLbl', false)) {
            var s = parseFloat(mxUtils.getValue(this.style, 'size', this.size)) * this.scale;

            return new mxRectangle(s, s, 0, 0);
        }

        return null;
    };

    mxCellRenderer.registerShape('cube', CubeShape);

    // 30度角的正切值常量，用于等距形状计算
    var tan30 = Math.tan(mxUtils.toRadians(30));
    var tan30Dx = (0.5 - tan30) / 2;

    // 等距矩形形状，支持大小样式
    /**
     * 等距矩形形状构造函数，继承自 mxActor。
     * 创建具有等距投影效果的矩形图形。
     */
    function IsoRectangleShape() {
        mxActor.call(this);
    };
    mxUtils.extend(IsoRectangleShape, mxActor);
    IsoRectangleShape.prototype.size = 20;
    IsoRectangleShape.prototype.redrawPath = function (path, x, y, w, h) {
        var m = Math.min(w, h / tan30);

        path.translate((w - m) / 2, (h - m) / 2 + m / 4);
        path.moveTo(0, 0.25 * m);
        path.lineTo(0.5 * m, m * tan30Dx);
        path.lineTo(m, 0.25 * m);
        path.lineTo(0.5 * m, (0.5 - tan30Dx) * m);
        path.lineTo(0, 0.25 * m);
        path.close();
        path.end();
    };

    mxCellRenderer.registerShape('isoRectangle', IsoRectangleShape);

    // 等距立方体形状，支持大小样式
    /**
     * 等距立方体形状构造函数，继承自 mxCylinder。
     * 创建具有等距投影效果的立方体图形。
     */
    function IsoCubeShape() {
        mxCylinder.call(this);
    };
    mxUtils.extend(IsoCubeShape, mxCylinder);
    IsoCubeShape.prototype.size = 20;
    IsoCubeShape.prototype.redrawPath = function (path, x, y, w, h, isForeground) {
        var m = Math.min(w, h / (0.5 + tan30));

        if (isForeground) {
            path.moveTo(0, 0.25 * m);
            path.lineTo(0.5 * m, (0.5 - tan30Dx) * m);
            path.lineTo(m, 0.25 * m);
            path.moveTo(0.5 * m, (0.5 - tan30Dx) * m);
            path.lineTo(0.5 * m, (1 - tan30Dx) * m);
            path.end();
        } else {
            path.translate((w - m) / 2, (h - m) / 2);
            path.moveTo(0, 0.25 * m);
            path.lineTo(0.5 * m, m * tan30Dx);
            path.lineTo(m, 0.25 * m);
            path.lineTo(m, 0.75 * m);
            path.lineTo(0.5 * m, (1 - tan30Dx) * m);
            path.lineTo(0, 0.75 * m);
            path.close();
            path.end();
        }
    };

    mxCellRenderer.registerShape('isoCube', IsoCubeShape);

    // 数据存储形状，支持大小样式
    /**
     * 数据存储形状构造函数，继承自 mxCylinder。
     * 创建数据库或数据存储的视觉表示，通常显示为圆柱形。
     */
    function DataStoreShape() {
        mxCylinder.call(this);
    };
    mxUtils.extend(DataStoreShape, mxCylinder);

    DataStoreShape.prototype.redrawPath = function (c, x, y, w, h, isForeground) {
        var dy = Math.min(h / 2, Math.round(h / 8) + this.strokewidth - 1);

        if ((isForeground && this.fill != null) || (!isForeground && this.fill == null)) {
            c.moveTo(0, dy);
            c.curveTo(0, 2 * dy, w, 2 * dy, w, dy);

            // Needs separate shapes for correct hit-detection
            if (!isForeground) {
                c.stroke();
                c.begin();
            }

            c.translate(0, dy / 2);
            c.moveTo(0, dy);
            c.curveTo(0, 2 * dy, w, 2 * dy, w, dy);

            // Needs separate shapes for correct hit-detection
            if (!isForeground) {
                c.stroke();
                c.begin();
            }

            c.translate(0, dy / 2);
            c.moveTo(0, dy);
            c.curveTo(0, 2 * dy, w, 2 * dy, w, dy);

            // Needs separate shapes for correct hit-detection
            if (!isForeground) {
                c.stroke();
                c.begin();
            }

            c.translate(0, -dy);
        }

        if (!isForeground) {
            c.moveTo(0, dy);
            c.curveTo(0, -dy / 3, w, -dy / 3, w, dy);
            c.lineTo(w, h - dy);
            c.curveTo(w, h + dy / 3, 0, h + dy / 3, 0, h - dy);
            c.close();
        }
    };
    DataStoreShape.prototype.getLabelMargins = function (rect) {
        return new mxRectangle(0, 2.5 * Math.min(rect.height / 2,
            Math.round(rect.height / 8) + this.strokewidth - 1), 0, 0);
    }

    mxCellRenderer.registerShape('datastore', DataStoreShape);

    // 便签形状，支持大小样式
    /**
     * 便签形状构造函数，继承自 mxCylinder。
     * 创建带有折角效果的便签或文档图形。
     */
    function NoteShape() {
        mxCylinder.call(this);
    };
    mxUtils.extend(NoteShape, mxCylinder);
    NoteShape.prototype.size = 30;
    NoteShape.prototype.darkOpacity = 0;

    NoteShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        var s = Math.max(0, Math.min(w, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))));
        var op = Math.max(-1, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'darkOpacity', this.darkOpacity))));
        c.translate(x, y);

        c.begin();
        c.moveTo(0, 0);
        c.lineTo(w - s, 0);
        c.lineTo(w, s);
        c.lineTo(w, h);
        c.lineTo(0, h);
        c.lineTo(0, 0);
        c.close();
        c.end();
        c.fillAndStroke();

        if (!this.outline) {
            c.setShadow(false);

            if (op != 0) {
                c.setFillAlpha(Math.abs(op));
                c.setFillColor((op < 0) ? '#FFFFFF' : '#000000');
                c.begin();
                c.moveTo(w - s, 0);
                c.lineTo(w - s, s);
                c.lineTo(w, s);
                c.close();
                c.fill();
            }

            c.begin();
            c.moveTo(w - s, 0);
            c.lineTo(w - s, s);
            c.lineTo(w, s);
            c.end();
            c.stroke();
        }
    };

    mxCellRenderer.registerShape('note', NoteShape);

    // 便签形状2，支持大小样式
    /**
     * 便签形状2构造函数，继承自 NoteShape。
     * 创建另一种样式的便签图形，支持不同的标签边距设置。
     */
    function NoteShape2() {
        NoteShape.call(this);
    };
    mxUtils.extend(NoteShape2, NoteShape);

    mxCellRenderer.registerShape('note2', NoteShape2);

    NoteShape2.prototype.getLabelMargins = function (rect) {
        if (mxUtils.getValue(this.style, 'boundedLbl', false)) {
            var size = mxUtils.getValue(this.style, 'size', 15);

            return new mxRectangle(0, Math.min(rect.height * this.scale, size * this.scale), 0, 0);
        }

        return null;
    };

    // 灵活立方体形状
    /**
     * 灵活立方体形状构造函数，继承自 mxShape。
     * 创建可调节角度的等距立方体图形。
     */
    function IsoCubeShape2() {
        mxShape.call(this);
    };
    mxUtils.extend(IsoCubeShape2, mxShape);
    IsoCubeShape2.prototype.isoAngle = 15;

    IsoCubeShape2.prototype.paintVertexShape = function (c, x, y, w, h) {
        var isoAngle = Math.max(0.01, Math.min(94, parseFloat(mxUtils.getValue(this.style, 'isoAngle', this.isoAngle)))) * Math.PI / 200;
        var isoH = Math.min(w * Math.tan(isoAngle), h * 0.5);

        c.translate(x, y);

        c.begin();
        c.moveTo(w * 0.5, 0);
        c.lineTo(w, isoH);
        c.lineTo(w, h - isoH);
        c.lineTo(w * 0.5, h);
        c.lineTo(0, h - isoH);
        c.lineTo(0, isoH);
        c.close();
        c.fillAndStroke();

        c.setShadow(false);

        c.begin();
        c.moveTo(0, isoH);
        c.lineTo(w * 0.5, 2 * isoH);
        c.lineTo(w, isoH);
        c.moveTo(w * 0.5, 2 * isoH);
        c.lineTo(w * 0.5, h);
        c.stroke();
    };

    mxCellRenderer.registerShape('isoCube2', IsoCubeShape2);

    // (遗留) 灵活圆柱形状
    /**
     * 灵活圆柱形状构造函数，继承自 mxShape。
     * 创建可调节高度的圆柱形图形，这是一个遗留实现。
     */
    function CylinderShape() {
        mxShape.call(this);
    };

    mxUtils.extend(CylinderShape, mxShape);

    CylinderShape.prototype.size = 15;

    CylinderShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        var size = Math.max(0, Math.min(h * 0.5, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));

        c.translate(x, y);

        if (size == 0) {
            c.rect(0, 0, w, h);
            c.fillAndStroke();
        } else {
            c.begin();
            c.moveTo(0, size);
            c.arcTo(w * 0.5, size, 0, 0, 1, w * 0.5, 0);
            c.arcTo(w * 0.5, size, 0, 0, 1, w, size);
            c.lineTo(w, h - size);
            c.arcTo(w * 0.5, size, 0, 0, 1, w * 0.5, h);
            c.arcTo(w * 0.5, size, 0, 0, 1, 0, h - size);
            c.close();
            c.fillAndStroke();

            c.setShadow(false);

            c.begin();
            c.moveTo(w, size);
            c.arcTo(w * 0.5, size, 0, 0, 1, w * 0.5, 2 * size);
            c.arcTo(w * 0.5, size, 0, 0, 1, 0, size);
            c.stroke();
        }
    };

    mxCellRenderer.registerShape('cylinder2', CylinderShape);

    // Flexible cylinder3 Shape with offset label
    function CylinderShape3(bounds, fill, stroke, strokewidth) {
        mxShape.call(this);
        this.bounds = bounds;
        this.fill = fill;
        this.stroke = stroke;
        this.strokewidth = (strokewidth != null) ? strokewidth : 1;
    };

    mxUtils.extend(CylinderShape3, mxCylinder);

    CylinderShape3.prototype.size = 15;

    CylinderShape3.prototype.paintVertexShape = function (c, x, y, w, h) {
        var size = Math.max(0, Math.min(h * 0.5, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var lid = mxUtils.getValue(this.style, 'lid', true);

        c.translate(x, y);

        if (size == 0) {
            c.rect(0, 0, w, h);
            c.fillAndStroke();
        } else {
            c.begin();

            if (lid) {
                c.moveTo(0, size);
                c.arcTo(w * 0.5, size, 0, 0, 1, w * 0.5, 0);
                c.arcTo(w * 0.5, size, 0, 0, 1, w, size);
            } else {
                c.moveTo(0, 0);
                c.arcTo(w * 0.5, size, 0, 0, 0, w * 0.5, size);
                c.arcTo(w * 0.5, size, 0, 0, 0, w, 0);
            }

            c.lineTo(w, h - size);
            c.arcTo(w * 0.5, size, 0, 0, 1, w * 0.5, h);
            c.arcTo(w * 0.5, size, 0, 0, 1, 0, h - size);
            c.close();
            c.fillAndStroke();

            c.setShadow(false);

            if (lid) {
                c.begin();
                c.moveTo(w, size);
                c.arcTo(w * 0.5, size, 0, 0, 1, w * 0.5, 2 * size);
                c.arcTo(w * 0.5, size, 0, 0, 1, 0, size);
                c.stroke();
            }
        }
    };

    mxCellRenderer.registerShape('cylinder3', CylinderShape3);

    // 开关形状，支持大小样式
    /**
     * 开关形状构造函数，继承自 mxActor。
     * 创建具有圆滑曲线的开关形图形。
     */
    function SwitchShape() {
        mxActor.call(this);
    };
    mxUtils.extend(SwitchShape, mxActor);
    SwitchShape.prototype.redrawPath = function (c, x, y, w, h) {
        var curve = 0.5;
        c.moveTo(0, 0);
        c.quadTo(w / 2, h * curve, w, 0);
        c.quadTo(w * (1 - curve), h / 2, w, h);
        c.quadTo(w / 2, h * (1 - curve), 0, h);
        c.quadTo(w * curve, h / 2, 0, 0);
        c.end();
    };

    mxCellRenderer.registerShape('switch', SwitchShape);

    // 文件夹形状，支持标签宽度、标签高度样式
    /**
     * 文件夹形状构造函数，继承自 mxCylinder。
     * 创建文件夹图标，支持自定义标签宽度和高度。
     */
    function FolderShape() {
        mxCylinder.call(this);
    };
    mxUtils.extend(FolderShape, mxCylinder);
    FolderShape.prototype.tabWidth = 60;
    FolderShape.prototype.tabHeight = 20;
    FolderShape.prototype.tabPosition = 'right';
    FolderShape.prototype.arcSize = 0.1;

    FolderShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        c.translate(x, y);

        var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'tabWidth', this.tabWidth))));
        var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'tabHeight', this.tabHeight))));
        var tp = mxUtils.getValue(this.style, 'tabPosition', this.tabPosition);
        var rounded = mxUtils.getValue(this.style, 'rounded', false);
        var absArcSize = mxUtils.getValue(this.style, 'absoluteArcSize', false);
        var arcSize = parseFloat(mxUtils.getValue(this.style, 'arcSize', this.arcSize));

        if (!absArcSize) {
            arcSize = Math.min(w, h) * arcSize;
        }

        arcSize = Math.min(arcSize, w * 0.5, (h - dy) * 0.5);

        dx = Math.max(dx, arcSize);
        dx = Math.min(w - arcSize, dx);

        if (!rounded) {
            arcSize = 0;
        }

        c.begin();

        if (tp == 'left') {
            c.moveTo(Math.max(arcSize, 0), dy);
            c.lineTo(Math.max(arcSize, 0), 0);
            c.lineTo(dx, 0);
            c.lineTo(dx, dy);
        }
        // Right is default
        else {
            c.moveTo(w - dx, dy);
            c.lineTo(w - dx, 0);
            c.lineTo(w - Math.max(arcSize, 0), 0);
            c.lineTo(w - Math.max(arcSize, 0), dy);
        }

        if (rounded) {
            c.moveTo(0, arcSize + dy);
            c.arcTo(arcSize, arcSize, 0, 0, 1, arcSize, dy);
            c.lineTo(w - arcSize, dy);
            c.arcTo(arcSize, arcSize, 0, 0, 1, w, arcSize + dy);
            c.lineTo(w, h - arcSize);
            c.arcTo(arcSize, arcSize, 0, 0, 1, w - arcSize, h);
            c.lineTo(arcSize, h);
            c.arcTo(arcSize, arcSize, 0, 0, 1, 0, h - arcSize);
        } else {
            c.moveTo(0, dy);
            c.lineTo(w, dy);
            c.lineTo(w, h);
            c.lineTo(0, h);
        }

        c.close();
        c.fillAndStroke();

        c.setShadow(false);

        var sym = mxUtils.getValue(this.style, 'folderSymbol', null);

        if (sym == 'triangle') {
            c.begin();
            c.moveTo(w - 30, dy + 20);
            c.lineTo(w - 20, dy + 10);
            c.lineTo(w - 10, dy + 20);
            c.close();
            c.stroke();
        }
    };

    mxCellRenderer.registerShape('folder', FolderShape);

    FolderShape.prototype.getLabelMargins = function (rect) {
        if (mxUtils.getValue(this.style, 'boundedLbl', false)) {
            var sizeY = mxUtils.getValue(this.style, 'tabHeight', 15) * this.scale;

            if (mxUtils.getValue(this.style, 'labelInHeader', false)) {
                var sizeX = mxUtils.getValue(this.style, 'tabWidth', 15) * this.scale;
                var sizeY = mxUtils.getValue(this.style, 'tabHeight', 15) * this.scale;
                var rounded = mxUtils.getValue(this.style, 'rounded', false);
                var absArcSize = mxUtils.getValue(this.style, 'absoluteArcSize', false);
                var arcSize = parseFloat(mxUtils.getValue(this.style, 'arcSize', this.arcSize));

                if (!absArcSize) {
                    arcSize = Math.min(rect.width, rect.height) * arcSize;
                }

                arcSize = Math.min(arcSize, rect.width * 0.5, (rect.height - sizeY) * 0.5);

                if (!rounded) {
                    arcSize = 0;
                }

                if (mxUtils.getValue(this.style, 'tabPosition', this.tabPosition) == 'left') {
                    return new mxRectangle(arcSize, 0, Math.min(rect.width, rect.width - sizeX), Math.min(rect.height, rect.height - sizeY));
                } else {
                    return new mxRectangle(Math.min(rect.width, rect.width - sizeX), 0, arcSize, Math.min(rect.height, rect.height - sizeY));
                }
            } else {
                return new mxRectangle(0, Math.min(rect.height, sizeY), 0, 0);
            }
        }

        return null;
    };

    //**********************************************************************************************************************************************************
    //UML State shape
    //**********************************************************************************************************************************************************
    function UMLStateShape() {
        mxCylinder.call(this);
    };
    mxUtils.extend(UMLStateShape, mxCylinder);
    UMLStateShape.prototype.arcSize = 0.1;

    UMLStateShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        c.translate(x, y);

        var rounded = mxUtils.getValue(this.style, 'rounded', false);
        var absArcSize = mxUtils.getValue(this.style, 'absoluteArcSize', false);
        var arcSize = parseFloat(mxUtils.getValue(this.style, 'arcSize', this.arcSize));
        var connPoint = mxUtils.getValue(this.style, 'umlStateConnection', null);

        if (!absArcSize) {
            arcSize = Math.min(w, h) * arcSize;
        }

        arcSize = Math.min(arcSize, w * 0.5, h * 0.5);

        if (!rounded) {
            arcSize = 0;
        }

        var dx = 0;

        if (connPoint != null) {
            dx = 10;
        }

        c.begin();
        c.moveTo(dx, arcSize);
        c.arcTo(arcSize, arcSize, 0, 0, 1, dx + arcSize, 0);
        c.lineTo(w - arcSize, 0);
        c.arcTo(arcSize, arcSize, 0, 0, 1, w, arcSize);
        c.lineTo(w, h - arcSize);
        c.arcTo(arcSize, arcSize, 0, 0, 1, w - arcSize, h);
        c.lineTo(dx + arcSize, h);
        c.arcTo(arcSize, arcSize, 0, 0, 1, dx, h - arcSize);
        c.close();
        c.fillAndStroke();

        c.setShadow(false);

        var sym = mxUtils.getValue(this.style, 'umlStateSymbol', null);

        if (sym == 'collapseState') {
            c.roundrect(w - 40, h - 20, 10, 10, 3, 3);
            c.stroke();
            c.roundrect(w - 20, h - 20, 10, 10, 3, 3);
            c.stroke();
            c.begin();
            c.moveTo(w - 30, h - 15);
            c.lineTo(w - 20, h - 15);
            c.stroke();
        }

        if (connPoint == 'connPointRefEntry') {
            c.ellipse(0, h * 0.5 - 10, 20, 20);
            c.fillAndStroke();
        } else if (connPoint == 'connPointRefExit') {
            c.ellipse(0, h * 0.5 - 10, 20, 20);
            c.fillAndStroke();

            c.begin();
            c.moveTo(5, h * 0.5 - 5);
            c.lineTo(15, h * 0.5 + 5);
            c.moveTo(15, h * 0.5 - 5);
            c.lineTo(5, h * 0.5 + 5);
            c.stroke();
        }
    };

    UMLStateShape.prototype.getLabelMargins = function (rect) {
        if (mxUtils.getValue(this.style, 'boundedLbl', false)) {
            var connPoint = mxUtils.getValue(this.style, 'umlStateConnection', null);

            if (connPoint != null) {
                return new mxRectangle(10 * this.scale, 0, 0, 0);
            }
        }

        return null;
    };

    mxCellRenderer.registerShape('umlState', UMLStateShape);

    // Card shape
    function CardShape() {
        mxActor.call(this);
    };
    mxUtils.extend(CardShape, mxActor);
    CardShape.prototype.size = 30;
    CardShape.prototype.isRoundable = function () {
        return true;
    };
    CardShape.prototype.redrawPath = function (c, x, y, w, h) {
        var s = Math.max(0, Math.min(w, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))));
        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        this.addPoints(c, [new mxPoint(s, 0), new mxPoint(w, 0), new mxPoint(w, h), new mxPoint(0, h), new mxPoint(0, s)],
            this.isRounded, arcSize, true);
        c.end();
    };

    mxCellRenderer.registerShape('card', CardShape);

    // Tape shape
    function TapeShape() {
        mxActor.call(this);
    };
    mxUtils.extend(TapeShape, mxActor);
    TapeShape.prototype.size = 0.4;
    TapeShape.prototype.redrawPath = function (c, x, y, w, h) {
        var dy = h * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var fy = 1.4;

        c.moveTo(0, dy / 2);
        c.quadTo(w / 4, dy * fy, w / 2, dy / 2);
        c.quadTo(w * 3 / 4, dy * (1 - fy), w, dy / 2);
        c.lineTo(w, h - dy / 2);
        c.quadTo(w * 3 / 4, h - dy * fy, w / 2, h - dy / 2);
        c.quadTo(w / 4, h - dy * (1 - fy), 0, h - dy / 2);
        c.lineTo(0, dy / 2);
        c.close();
        c.end();
    };

    TapeShape.prototype.getLabelBounds = function (rect) {
        if (mxUtils.getValue(this.style, 'boundedLbl', false)) {
            var size = mxUtils.getValue(this.style, 'size', this.size);
            var w = rect.width;
            var h = rect.height;

            if (this.direction == null ||
                this.direction == mxConstants.DIRECTION_EAST ||
                this.direction == mxConstants.DIRECTION_WEST) {
                var dy = h * size;

                return new mxRectangle(rect.x, rect.y + dy, w, h - 2 * dy);
            } else {
                var dx = w * size;

                return new mxRectangle(rect.x + dx, rect.y, w - 2 * dx, h);
            }
        }

        return rect;
    };

    mxCellRenderer.registerShape('tape', TapeShape);

    // Document shape
    function DocumentShape() {
        mxActor.call(this);
    };
    mxUtils.extend(DocumentShape, mxActor);
    DocumentShape.prototype.size = 0.3;
    DocumentShape.prototype.getLabelMargins = function (rect) {
        if (mxUtils.getValue(this.style, 'boundedLbl', false)) {
            return new mxRectangle(0, 0, 0, parseFloat(mxUtils.getValue(
                this.style, 'size', this.size)) * rect.height);
        }

        return null;
    };
    DocumentShape.prototype.redrawPath = function (c, x, y, w, h) {
        var dy = h * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var fy = 1.4;

        c.moveTo(0, 0);
        c.lineTo(w, 0);
        c.lineTo(w, h - dy / 2);
        c.quadTo(w * 3 / 4, h - dy * fy, w / 2, h - dy / 2);
        c.quadTo(w / 4, h - dy * (1 - fy), 0, h - dy / 2);
        c.lineTo(0, dy / 2);
        c.close();
        c.end();
    };

    mxCellRenderer.registerShape('document', DocumentShape);

    var cylinderGetCylinderSize = mxCylinder.prototype.getCylinderSize;

    mxCylinder.prototype.getCylinderSize = function (x, y, w, h) {
        var size = mxUtils.getValue(this.style, 'size');

        if (size != null) {
            return h * Math.max(0, Math.min(1, size));
        } else {
            return cylinderGetCylinderSize.apply(this, arguments);
        }
    };

    mxCylinder.prototype.getLabelMargins = function (rect) {
        if (mxUtils.getValue(this.style, 'boundedLbl', false)) {
            var size = mxUtils.getValue(this.style, 'size', 0.15) * 2;

            return new mxRectangle(0, Math.min(this.maxHeight * this.scale, rect.height * size), 0, 0);
        }

        return null;
    };

    CylinderShape3.prototype.getLabelMargins = function (rect) {
        if (mxUtils.getValue(this.style, 'boundedLbl', false)) {
            var size = mxUtils.getValue(this.style, 'size', 15);

            if (!mxUtils.getValue(this.style, 'lid', true)) {
                size /= 2;
            }

            return new mxRectangle(0, Math.min(rect.height * this.scale, size * 2 * this.scale), 0, Math.max(0, size * 0.3 * this.scale));
        }

        return null;
    };

    FolderShape.prototype.getLabelMargins = function (rect) {
        if (mxUtils.getValue(this.style, 'boundedLbl', false)) {
            var sizeY = mxUtils.getValue(this.style, 'tabHeight', 15) * this.scale;

            if (mxUtils.getValue(this.style, 'labelInHeader', false)) {
                var sizeX = mxUtils.getValue(this.style, 'tabWidth', 15) * this.scale;
                var sizeY = mxUtils.getValue(this.style, 'tabHeight', 15) * this.scale;
                var rounded = mxUtils.getValue(this.style, 'rounded', false);
                var absArcSize = mxUtils.getValue(this.style, 'absoluteArcSize', false);
                var arcSize = parseFloat(mxUtils.getValue(this.style, 'arcSize', this.arcSize));

                if (!absArcSize) {
                    arcSize = Math.min(rect.width, rect.height) * arcSize;
                }

                arcSize = Math.min(arcSize, rect.width * 0.5, (rect.height - sizeY) * 0.5);

                if (!rounded) {
                    arcSize = 0;
                }

                if (mxUtils.getValue(this.style, 'tabPosition', this.tabPosition) == 'left') {
                    return new mxRectangle(arcSize, 0, Math.min(rect.width, rect.width - sizeX), Math.min(rect.height, rect.height - sizeY));
                } else {
                    return new mxRectangle(Math.min(rect.width, rect.width - sizeX), 0, arcSize, Math.min(rect.height, rect.height - sizeY));
                }
            } else {
                return new mxRectangle(0, Math.min(rect.height, sizeY), 0, 0);
            }
        }

        return null;
    };

    UMLStateShape.prototype.getLabelMargins = function (rect) {
        if (mxUtils.getValue(this.style, 'boundedLbl', false)) {
            var connPoint = mxUtils.getValue(this.style, 'umlStateConnection', null);

            if (connPoint != null) {
                return new mxRectangle(10 * this.scale, 0, 0, 0);
            }
        }

        return null;
    };

    NoteShape2.prototype.getLabelMargins = function (rect) {
        if (mxUtils.getValue(this.style, 'boundedLbl', false)) {
            var size = mxUtils.getValue(this.style, 'size', 15);

            return new mxRectangle(0, Math.min(rect.height * this.scale, size * this.scale), 0, Math.max(0, size * this.scale));
        }

        return null;
    };

    // Parallelogram shape
    function ParallelogramShape() {
        mxActor.call(this);
    };
    mxUtils.extend(ParallelogramShape, mxActor);
    ParallelogramShape.prototype.size = 0.2;
    ParallelogramShape.prototype.fixedSize = 20;
    ParallelogramShape.prototype.isRoundable = function () {
        return true;
    };
    ParallelogramShape.prototype.redrawPath = function (c, x, y, w, h) {
        var fixed = mxUtils.getValue(this.style, 'fixedSize', '0') != '0';

        var dx = (fixed) ? Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'size', this.fixedSize)))) : w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        this.addPoints(c, [new mxPoint(0, h), new mxPoint(dx, 0), new mxPoint(w, 0), new mxPoint(w - dx, h)],
            this.isRounded, arcSize, true);
        c.end();
    };

    mxCellRenderer.registerShape('parallelogram', ParallelogramShape);

    // Trapezoid shape
    function TrapezoidShape() {
        mxActor.call(this);
    };
    mxUtils.extend(TrapezoidShape, mxActor);
    TrapezoidShape.prototype.size = 0.2;
    TrapezoidShape.prototype.fixedSize = 20;
    TrapezoidShape.prototype.isRoundable = function () {
        return true;
    };
    TrapezoidShape.prototype.redrawPath = function (c, x, y, w, h) {

        var fixed = mxUtils.getValue(this.style, 'fixedSize', '0') != '0';

        var dx = (fixed) ? Math.max(0, Math.min(w * 0.5, parseFloat(mxUtils.getValue(this.style, 'size', this.fixedSize)))) : w * Math.max(0, Math.min(0.5, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        this.addPoints(c, [new mxPoint(0, h), new mxPoint(dx, 0), new mxPoint(w - dx, 0), new mxPoint(w, h)],
            this.isRounded, arcSize, true);
    };

    mxCellRenderer.registerShape('trapezoid', TrapezoidShape);

    // Curly Bracket shape
    function CurlyBracketShape() {
        mxActor.call(this);
    };
    mxUtils.extend(CurlyBracketShape, mxActor);
    CurlyBracketShape.prototype.size = 0.5;
    CurlyBracketShape.prototype.redrawPath = function (c, x, y, w, h) {
        c.setFillColor(null);
        var s = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        this.addPoints(c, [new mxPoint(w, 0), new mxPoint(s, 0), new mxPoint(s, h / 2),
            new mxPoint(0, h / 2), new mxPoint(s, h / 2), new mxPoint(s, h),
            new mxPoint(w, h)], this.isRounded, arcSize, false);
        c.end();
    };

    mxCellRenderer.registerShape('curlyBracket', CurlyBracketShape);

    // Parallel marker shape
    function ParallelMarkerShape() {
        mxActor.call(this);
    };
    mxUtils.extend(ParallelMarkerShape, mxActor);
    ParallelMarkerShape.prototype.redrawPath = function (c, x, y, w, h) {
        c.setStrokeWidth(1);
        c.setFillColor(this.stroke);
        var w2 = w / 5;
        c.rect(0, 0, w2, h);
        c.fillAndStroke();
        c.rect(2 * w2, 0, w2, h);
        c.fillAndStroke();
        c.rect(4 * w2, 0, w2, h);
        c.fillAndStroke();
    };

    mxCellRenderer.registerShape('parallelMarker', ParallelMarkerShape);

    /**
     * Adds handJiggle style (jiggle=n sets jiggle)
     */
    function HandJiggle(canvas, defaultVariation) {
        this.canvas = canvas;

        // Avoids "spikes" in the output
        this.canvas.setLineJoin('round');
        this.canvas.setLineCap('round');

        this.defaultVariation = defaultVariation;

        this.originalLineTo = this.canvas.lineTo;
        this.canvas.lineTo = mxUtils.bind(this, HandJiggle.prototype.lineTo);

        this.originalMoveTo = this.canvas.moveTo;
        this.canvas.moveTo = mxUtils.bind(this, HandJiggle.prototype.moveTo);

        this.originalClose = this.canvas.close;
        this.canvas.close = mxUtils.bind(this, HandJiggle.prototype.close);

        this.originalQuadTo = this.canvas.quadTo;
        this.canvas.quadTo = mxUtils.bind(this, HandJiggle.prototype.quadTo);

        this.originalCurveTo = this.canvas.curveTo;
        this.canvas.curveTo = mxUtils.bind(this, HandJiggle.prototype.curveTo);

        this.originalArcTo = this.canvas.arcTo;
        this.canvas.arcTo = mxUtils.bind(this, HandJiggle.prototype.arcTo);
    };

    HandJiggle.prototype.moveTo = function (endX, endY) {
        this.originalMoveTo.apply(this.canvas, arguments);
        this.lastX = endX;
        this.lastY = endY;
        this.firstX = endX;
        this.firstY = endY;
    };

    HandJiggle.prototype.close = function () {
        if (this.firstX != null && this.firstY != null) {
            this.lineTo(this.firstX, this.firstY);
            this.originalClose.apply(this.canvas, arguments);
        }

        this.originalClose.apply(this.canvas, arguments);
    };

    HandJiggle.prototype.quadTo = function (x1, y1, x2, y2) {
        this.originalQuadTo.apply(this.canvas, arguments);
        this.lastX = x2;
        this.lastY = y2;
    };

    HandJiggle.prototype.curveTo = function (x1, y1, x2, y2, x3, y3) {
        this.originalCurveTo.apply(this.canvas, arguments);
        this.lastX = x3;
        this.lastY = y3;
    };

    HandJiggle.prototype.arcTo = function (rx, ry, angle, largeArcFlag, sweepFlag, x, y) {
        this.originalArcTo.apply(this.canvas, arguments);
        this.lastX = x;
        this.lastY = y;
    };

    HandJiggle.prototype.lineTo = function (endX, endY) {
        // LATER: Check why this.canvas.lastX cannot be used
        if (this.lastX != null && this.lastY != null) {
            var dx = Math.abs(endX - this.lastX);
            var dy = Math.abs(endY - this.lastY);
            var dist = Math.sqrt(dx * dx + dy * dy);

            if (dist < 2) {
                this.originalLineTo.apply(this.canvas, arguments);
                this.lastX = endX;
                this.lastY = endY;

                return;
            }

            var segs = Math.round(dist / 10);
            var variation = this.defaultVariation;

            if (segs < 5) {
                segs = 5;
                variation /= 3;
            }

            function sign(x) {
                return typeof x === 'number' ? x ? x < 0 ? -1 : 1 : x === x ? 0 : NaN : NaN;
            }

            var stepX = sign(endX - this.lastX) * dx / segs;
            var stepY = sign(endY - this.lastY) * dy / segs;

            var fx = dx / dist;
            var fy = dy / dist;

            for (var s = 0; s < segs; s++) {
                var x = stepX * s + this.lastX;
                var y = stepY * s + this.lastY;

                var offset = (Math.random() - 0.5) * variation;
                this.originalLineTo.call(this.canvas, x - offset * fy, y - offset * fx);
            }

            this.originalLineTo.call(this.canvas, endX, endY);
            this.lastX = endX;
            this.lastY = endY;
        } else {
            this.originalLineTo.apply(this.canvas, arguments);
            this.lastX = endX;
            this.lastY = endY;
        }
    };

    HandJiggle.prototype.destroy = function () {
        this.canvas.lineTo = this.originalLineTo;
        this.canvas.moveTo = this.originalMoveTo;
        this.canvas.close = this.originalClose;
        this.canvas.quadTo = this.originalQuadTo;
        this.canvas.curveTo = this.originalCurveTo;
        this.canvas.arcTo = this.originalArcTo;
    };

    // Installs hand jiggle for comic and sketch style
    mxShape.prototype.defaultJiggle = 1.5;

    var shapeBeforePaint = mxShape.prototype.beforePaint;
    mxShape.prototype.beforePaint = function (c) {
        shapeBeforePaint.apply(this, arguments);

        if (c.handJiggle == null) {
            c.handJiggle = this.createHandJiggle(c);
        }
    };

    var shapeAfterPaint = mxShape.prototype.afterPaint;
    mxShape.prototype.afterPaint = function (c) {
        shapeAfterPaint.apply(this, arguments);

        if (c.handJiggle != null) {
            c.handJiggle.destroy();
            delete c.handJiggle;
        }
    };

    // Returns a new HandJiggle canvas
    mxShape.prototype.createComicCanvas = function (c) {
        return new HandJiggle(c, mxUtils.getValue(this.style, 'jiggle', this.defaultJiggle));
    };

    // Overrides to avoid call to rect
    mxShape.prototype.createHandJiggle = function (c) {
        if (!this.outline && this.style != null && mxUtils.getValue(this.style, 'comic', '0') != '0') {
            return this.createComicCanvas(c);
        }

        return null;
    };

    // Sets default jiggle for diamond
    mxRhombus.prototype.defaultJiggle = 2;

    // Overrides to avoid call to rect
    var mxRectangleShapeIsHtmlAllowed0 = mxRectangleShape.prototype.isHtmlAllowed;
    mxRectangleShape.prototype.isHtmlAllowed = function () {
        return !this.outline && (this.style == null || (mxUtils.getValue(this.style, 'comic', '0') == '0' &&
            mxUtils.getValue(this.style, 'sketch', (urlParams['rough'] == '1') ? '1' : '0') == '0')) &&
            mxRectangleShapeIsHtmlAllowed0.apply(this, arguments);
    };

    var mxRectangleShapePaintBackground0 = mxRectangleShape.prototype.paintBackground;
    mxRectangleShape.prototype.paintBackground = function (c, x, y, w, h) {
        if (c.handJiggle == null || c.handJiggle.constructor != HandJiggle) {
            mxRectangleShapePaintBackground0.apply(this, arguments);
        } else {
            var events = true;

            if (this.style != null) {
                events = mxUtils.getValue(this.style, mxConstants.STYLE_POINTER_EVENTS, '1') == '1';
            }

            if (events || (this.fill != null && this.fill != mxConstants.NONE) ||
                (this.stroke != null && this.stroke != mxConstants.NONE)) {
                if (!events && (this.fill == null || this.fill == mxConstants.NONE)) {
                    c.pointerEvents = false;
                }

                c.begin();

                if (this.isRounded) {
                    var r = 0;

                    if (mxUtils.getValue(this.style, mxConstants.STYLE_ABSOLUTE_ARCSIZE, 0) == '1') {
                        r = Math.min(w / 2, Math.min(h / 2, mxUtils.getValue(this.style,
                            mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2));
                    } else {
                        var f = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE,
                            mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) / 100;
                        r = Math.min(w * f, h * f);
                    }

                    c.moveTo(x + r, y);
                    c.lineTo(x + w - r, y);
                    c.quadTo(x + w, y, x + w, y + r);
                    c.lineTo(x + w, y + h - r);
                    c.quadTo(x + w, y + h, x + w - r, y + h);
                    c.lineTo(x + r, y + h);
                    c.quadTo(x, y + h, x, y + h - r);
                    c.lineTo(x, y + r);
                    c.quadTo(x, y, x + r, y);
                } else {
                    c.moveTo(x, y);
                    c.lineTo(x + w, y);
                    c.lineTo(x + w, y + h);
                    c.lineTo(x, y + h);
                    c.lineTo(x, y);
                }

                // LATER: Check if close is needed here
                c.close();
                c.end();

                c.fillAndStroke();
            }
        }
    };

    /**
     * Disables glass effect with hand jiggle.
     */
    var mxRectangleShapePaintForeground0 = mxRectangleShape.prototype.paintForeground;
    mxRectangleShape.prototype.paintForeground = function (c, x, y, w, h) {
        if (c.handJiggle == null) {
            mxRectangleShapePaintForeground0.apply(this, arguments);
        }
    };

    // End of hand jiggle integration

    // Process Shape
    function ProcessShape() {
        mxRectangleShape.call(this);
    };
    mxUtils.extend(ProcessShape, mxRectangleShape);
    ProcessShape.prototype.size = 0.1;
    ProcessShape.prototype.fixedSize = false;

    ProcessShape.prototype.isHtmlAllowed = function () {
        return false;
    };
    ProcessShape.prototype.getLabelBounds = function (rect) {
        if (mxUtils.getValue(this.state.style, mxConstants.STYLE_HORIZONTAL, true) ==
            (this.direction == null ||
                this.direction == mxConstants.DIRECTION_EAST ||
                this.direction == mxConstants.DIRECTION_WEST)) {
            var w = rect.width;
            var h = rect.height;
            var r = new mxRectangle(rect.x, rect.y, w, h);

            var inset = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));

            if (this.isRounded) {
                var f = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE,
                    mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) / 100;
                inset = Math.max(inset, Math.min(w * f, h * f));
            }

            r.x += Math.round(inset);
            r.width -= Math.round(2 * inset);

            return r;
        }

        return rect;
    };

    ProcessShape.prototype.paintForeground = function (c, x, y, w, h) {
        var isFixedSize = mxUtils.getValue(this.style, 'fixedSize', this.fixedSize);
        var inset = parseFloat(mxUtils.getValue(this.style, 'size', this.size));

        if (isFixedSize) {
            inset = Math.max(0, Math.min(w, inset));
        } else {
            inset = w * Math.max(0, Math.min(1, inset));
        }

        if (this.isRounded) {
            var f = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE,
                mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) / 100;
            inset = Math.max(inset, Math.min(w * f, h * f));
        }

        // Crisp rendering of inner lines
        inset = Math.round(inset);

        c.begin();
        c.moveTo(x + inset, y);
        c.lineTo(x + inset, y + h);
        c.moveTo(x + w - inset, y);
        c.lineTo(x + w - inset, y + h);
        c.end();
        c.stroke();
        mxRectangleShape.prototype.paintForeground.apply(this, arguments);
    };

    mxCellRenderer.registerShape('process', ProcessShape);
    //Register the same shape with another name for backwards compatibility
    mxCellRenderer.registerShape('process2', ProcessShape);

    // Transparent Shape
    function TransparentShape() {
        mxRectangleShape.call(this);
    };
    mxUtils.extend(TransparentShape, mxRectangleShape);
    TransparentShape.prototype.paintBackground = function (c, x, y, w, h) {
        c.setFillColor(mxConstants.NONE);
        c.rect(x, y, w, h);
        c.fill();
    };
    TransparentShape.prototype.paintForeground = function (c, x, y, w, h) {
    };

    mxCellRenderer.registerShape('transparent', TransparentShape);

    // Callout shape
    function CalloutShape() {
        mxActor.call(this);
    };
    mxUtils.extend(CalloutShape, mxHexagon);
    CalloutShape.prototype.size = 30;
    CalloutShape.prototype.position = 0.5;
    CalloutShape.prototype.position2 = 0.5;
    CalloutShape.prototype.base = 20;
    CalloutShape.prototype.getLabelMargins = function () {
        return new mxRectangle(0, 0, 0, parseFloat(mxUtils.getValue(
            this.style, 'size', this.size)) * this.scale);
    };
    CalloutShape.prototype.isRoundable = function () {
        return true;
    };
    CalloutShape.prototype.redrawPath = function (c, x, y, w, h) {
        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        var s = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var dx = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'position', this.position))));
        var dx2 = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'position2', this.position2))));
        var base = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'base', this.base))));

        this.addPoints(c, [new mxPoint(0, 0), new mxPoint(w, 0), new mxPoint(w, h - s),
                new mxPoint(Math.min(w, dx + base), h - s), new mxPoint(dx2, h),
                new mxPoint(Math.max(0, dx), h - s), new mxPoint(0, h - s)],
            this.isRounded, arcSize, true, [4]);
    };

    mxCellRenderer.registerShape('callout', CalloutShape);

    // Step shape
    /**
     * 步骤形状构造函数，继承自 mxActor。
     * 创建阶梯状或步骤式图形，常用于流程图中的步骤表示。
     */
    function StepShape() {
        mxActor.call(this);
    };
    mxUtils.extend(StepShape, mxActor);
    StepShape.prototype.size = 0.2;
    StepShape.prototype.fixedSize = 20;
    StepShape.prototype.isRoundable = function () {
        return true;
    };
    StepShape.prototype.redrawPath = function (c, x, y, w, h) {
        var fixed = mxUtils.getValue(this.style, 'fixedSize', '0') != '0';
        var s = (fixed) ? Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'size', this.fixedSize)))) :
            w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        this.addPoints(c, [new mxPoint(0, 0), new mxPoint(w - s, 0), new mxPoint(w, h / 2), new mxPoint(w - s, h),
            new mxPoint(0, h), new mxPoint(s, h / 2)], this.isRounded, arcSize, true);
        c.end();
    };

    mxCellRenderer.registerShape('step', StepShape);

    // 六角形形状
    /**
     * 六角形形状构造函数，继承自 mxActor。
     * 创建六边形图形，常用于流程图和网络图中。
     */
    function HexagonShape() {
        mxActor.call(this);
    };
    mxUtils.extend(HexagonShape, mxHexagon);
    HexagonShape.prototype.size = 0.25;
    HexagonShape.prototype.fixedSize = 20;
    HexagonShape.prototype.isRoundable = function () {
        return true;
    };
    HexagonShape.prototype.redrawPath = function (c, x, y, w, h) {
        var fixed = mxUtils.getValue(this.style, 'fixedSize', '0') != '0';
        var s = (fixed) ? Math.max(0, Math.min(w * 0.5, parseFloat(mxUtils.getValue(this.style, 'size', this.fixedSize)))) :
            w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        this.addPoints(c, [new mxPoint(s, 0), new mxPoint(w - s, 0), new mxPoint(w, 0.5 * h), new mxPoint(w - s, h),
            new mxPoint(s, h), new mxPoint(0, 0.5 * h)], this.isRounded, arcSize, true);
    };

    mxCellRenderer.registerShape('hexagon', HexagonShape);

    // 加号形状
    /**
     * 加号形状构造函数，继承自 mxRectangleShape。
     * 创建十字形或加号形图形，常用于表示添加或连接操作。
     */
    function PlusShape() {
        mxRectangleShape.call(this);
    };
    mxUtils.extend(PlusShape, mxRectangleShape);
    PlusShape.prototype.isHtmlAllowed = function () {
        return false;
    };
    PlusShape.prototype.paintForeground = function (c, x, y, w, h) {
        var border = Math.min(w / 5, h / 5) + 1;

        c.begin();
        c.moveTo(x + w / 2, y + border);
        c.lineTo(x + w / 2, y + h - border);
        c.moveTo(x + border, y + h / 2);
        c.lineTo(x + w - border, y + h / 2);
        c.end();
        c.stroke();
        mxRectangleShape.prototype.paintForeground.apply(this, arguments);
    };

    mxCellRenderer.registerShape('plus', PlusShape);

    // Overrides painting of rhombus shape to allow for double style
    var mxRhombusPaintVertexShape = mxRhombus.prototype.paintVertexShape;
    mxRhombus.prototype.getLabelBounds = function (rect) {
        if (this.style['double'] == 1) {
            var margin = (Math.max(2, this.strokewidth + 1) * 2 + parseFloat(
                this.style[mxConstants.STYLE_MARGIN] || 0)) * this.scale;

            return new mxRectangle(rect.x + margin, rect.y + margin,
                rect.width - 2 * margin, rect.height - 2 * margin);
        }

        return rect;
    };
    mxRhombus.prototype.paintVertexShape = function (c, x, y, w, h) {
        mxRhombusPaintVertexShape.apply(this, arguments);

        if (!this.outline && this.style['double'] == 1) {
            var margin = Math.max(2, this.strokewidth + 1) * 2 +
                parseFloat(this.style[mxConstants.STYLE_MARGIN] || 0);
            x += margin;
            y += margin;
            w -= 2 * margin;
            h -= 2 * margin;

            if (w > 0 && h > 0) {
                c.setShadow(false);

                // Workaround for closure compiler bug where the lines with x and y above
                // are removed if arguments is used as second argument in call below.
                mxRhombusPaintVertexShape.apply(this, [c, x, y, w, h]);
            }
        }
    };

    // CompositeShape
    function ExtendedShape() {
        mxRectangleShape.call(this);
    };
    mxUtils.extend(ExtendedShape, mxRectangleShape);
    ExtendedShape.prototype.isHtmlAllowed = function () {
        return false;
    };
    ExtendedShape.prototype.getLabelBounds = function (rect) {
        if (this.style['double'] == 1) {
            var margin = (Math.max(2, this.strokewidth + 1) + parseFloat(
                this.style[mxConstants.STYLE_MARGIN] || 0)) * this.scale;

            return new mxRectangle(rect.x + margin, rect.y + margin,
                rect.width - 2 * margin, rect.height - 2 * margin);
        }

        return rect;
    };

    ExtendedShape.prototype.paintForeground = function (c, x, y, w, h) {
        if (this.style != null) {
            if (!this.outline && this.style['double'] == 1) {
                var margin = Math.max(2, this.strokewidth + 1) + parseFloat(this.style[mxConstants.STYLE_MARGIN] || 0);
                x += margin;
                y += margin;
                w -= 2 * margin;
                h -= 2 * margin;

                if (w > 0 && h > 0) {
                    mxRectangleShape.prototype.paintBackground.apply(this, arguments);
                }
            }

            c.setDashed(false);

            // Draws the symbols defined in the style. The symbols are
            // numbered from 1...n. Possible postfixes are align,
            // verticalAlign, spacing, arcSpacing, width, height
            var counter = 0;
            var shape = null;

            do {
                shape = mxCellRenderer.defaultShapes[this.style['symbol' + counter]];

                if (shape != null) {
                    var align = this.style['symbol' + counter + 'Align'];
                    var valign = this.style['symbol' + counter + 'VerticalAlign'];
                    var width = this.style['symbol' + counter + 'Width'];
                    var height = this.style['symbol' + counter + 'Height'];
                    var spacing = this.style['symbol' + counter + 'Spacing'] || 0;
                    var vspacing = this.style['symbol' + counter + 'VSpacing'] || spacing;
                    var arcspacing = this.style['symbol' + counter + 'ArcSpacing'];

                    if (arcspacing != null) {
                        var arcSize = this.getArcSize(w + this.strokewidth, h + this.strokewidth) * arcspacing;
                        spacing += arcSize;
                        vspacing += arcSize;
                    }

                    var x2 = x;
                    var y2 = y;

                    if (align == mxConstants.ALIGN_CENTER) {
                        x2 += (w - width) / 2;
                    } else if (align == mxConstants.ALIGN_RIGHT) {
                        x2 += w - width - spacing;
                    } else {
                        x2 += spacing;
                    }

                    if (valign == mxConstants.ALIGN_MIDDLE) {
                        y2 += (h - height) / 2;
                    } else if (valign == mxConstants.ALIGN_BOTTOM) {
                        y2 += h - height - vspacing;
                    } else {
                        y2 += vspacing;
                    }

                    c.save();

                    // Small hack to pass style along into subshape
                    var tmp = new shape();
                    // TODO: Clone style and override settings (eg. strokewidth)
                    tmp.style = this.style;
                    shape.prototype.paintVertexShape.call(tmp, c, x2, y2, width, height);
                    c.restore();
                }

                counter++;
            }
            while (shape != null);
        }

        // Paints glass effect
        mxRectangleShape.prototype.paintForeground.apply(this, arguments);
    };

    mxCellRenderer.registerShape('ext', ExtendedShape);

    // Tape Shape, supports size style
    function MessageShape() {
        mxCylinder.call(this);
    };
    mxUtils.extend(MessageShape, mxCylinder);
    MessageShape.prototype.redrawPath = function (path, x, y, w, h, isForeground) {
        if (isForeground) {
            path.moveTo(0, 0);
            path.lineTo(w / 2, h / 2);
            path.lineTo(w, 0);
            path.end();
        } else {
            path.moveTo(0, 0);
            path.lineTo(w, 0);
            path.lineTo(w, h);
            path.lineTo(0, h);
            path.close();
        }
    };

    mxCellRenderer.registerShape('message', MessageShape);

    // UML Actor Shape
    function UmlActorShape() {
        mxShape.call(this);
    };
    mxUtils.extend(UmlActorShape, mxShape);
    UmlActorShape.prototype.paintBackground = function (c, x, y, w, h) {
        c.translate(x, y);

        // Head
        c.ellipse(w / 4, 0, w / 2, h / 4);
        c.fillAndStroke();

        c.begin();
        c.moveTo(w / 2, h / 4);
        c.lineTo(w / 2, 2 * h / 3);

        // Arms
        c.moveTo(w / 2, h / 3);
        c.lineTo(0, h / 3);
        c.moveTo(w / 2, h / 3);
        c.lineTo(w, h / 3);

        // Legs
        c.moveTo(w / 2, 2 * h / 3);
        c.lineTo(0, h);
        c.moveTo(w / 2, 2 * h / 3);
        c.lineTo(w, h);
        c.end();

        c.stroke();
    };

    // Replaces existing actor shape
    mxCellRenderer.registerShape('umlActor', UmlActorShape);

    ////////////// UML Boundary Shape ///////////////
    function UmlBoundaryShape() {
        mxShape.call(this);
    };
    mxUtils.extend(UmlBoundaryShape, mxShape);
    UmlBoundaryShape.prototype.getLabelMargins = function (rect) {
        return new mxRectangle(rect.width / 6, 0, 0, 0);
    };
    UmlBoundaryShape.prototype.paintBackground = function (c, x, y, w, h) {
        c.translate(x, y);

        // Base line
        c.begin();
        c.moveTo(0, h / 4);
        c.lineTo(0, h * 3 / 4);
        c.end();
        c.stroke();

        // Horizontal line
        c.begin();
        c.moveTo(0, h / 2);
        c.lineTo(w / 6, h / 2);
        c.end();
        c.stroke();

        // Circle
        c.ellipse(w / 6, 0, w * 5 / 6, h);
        c.fillAndStroke();
    };

    mxCellRenderer.registerShape('umlBoundary', UmlBoundaryShape);

    // UML Entity Shape
    function UmlEntityShape() {
        mxEllipse.call(this);
    };
    mxUtils.extend(UmlEntityShape, mxEllipse);
    UmlEntityShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        mxEllipse.prototype.paintVertexShape.apply(this, arguments);

        c.begin();
        c.moveTo(x + w / 8, y + h);
        c.lineTo(x + w * 7 / 8, y + h);
        c.end();
        c.stroke();
    };

    mxCellRenderer.registerShape('umlEntity', UmlEntityShape);

    // UML Destroy Shape
    function UmlDestroyShape() {
        mxShape.call(this);
    };
    mxUtils.extend(UmlDestroyShape, mxShape);
    UmlDestroyShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        c.translate(x, y);

        c.begin();
        c.moveTo(w, 0);
        c.lineTo(0, h);
        c.moveTo(0, 0);
        c.lineTo(w, h);
        c.end();
        c.stroke();
    };

    mxCellRenderer.registerShape('umlDestroy', UmlDestroyShape);

    // UML Control Shape
    function UmlControlShape() {
        mxShape.call(this);
    };
    mxUtils.extend(UmlControlShape, mxShape);
    UmlControlShape.prototype.getLabelBounds = function (rect) {
        return new mxRectangle(rect.x, rect.y + rect.height / 8, rect.width, rect.height * 7 / 8);
    };
    UmlControlShape.prototype.paintBackground = function (c, x, y, w, h) {
        c.translate(x, y);

        // Upper line
        c.begin();
        c.moveTo(w * 3 / 8, h / 8 * 1.1);
        c.lineTo(w * 5 / 8, 0);
        c.end();
        c.stroke();

        // Circle
        c.ellipse(0, h / 8, w, h * 7 / 8);
        c.fillAndStroke();
    };
    UmlControlShape.prototype.paintForeground = function (c, x, y, w, h) {
        // Lower line
        c.begin();
        c.moveTo(w * 3 / 8, h / 8 * 1.1);
        c.lineTo(w * 5 / 8, h / 4);
        c.end();
        c.stroke();
    };

    // Replaces existing actor shape
    mxCellRenderer.registerShape('umlControl', UmlControlShape);

    // UML Lifeline Shape
    function UmlLifeline() {
        mxRectangleShape.call(this);
    };
    mxUtils.extend(UmlLifeline, mxRectangleShape);
    UmlLifeline.prototype.size = 40;
    UmlLifeline.prototype.isHtmlAllowed = function () {
        return false;
    };
    UmlLifeline.prototype.getLabelBounds = function (rect) {
        var size = Math.max(0, Math.min(rect.height, parseFloat(
            mxUtils.getValue(this.style, 'size', this.size)) * this.scale));

        return new mxRectangle(rect.x, rect.y, rect.width, size);
    };
    UmlLifeline.prototype.paintBackground = function (c, x, y, w, h) {
        var size = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var participant = mxUtils.getValue(this.style, 'participant');

        if (participant == null || this.state == null) {
            mxRectangleShape.prototype.paintBackground.call(this, c, x, y, w, size);
        } else {
            var ctor = this.state.view.graph.cellRenderer.getShape(participant);

            if (ctor != null && ctor != UmlLifeline) {
                var shape = new ctor();
                shape.apply(this.state);
                c.save();
                shape.paintVertexShape(c, x, y, w, size);
                c.restore();
            }
        }

        if (size < h) {
            c.setDashed(mxUtils.getValue(this.style, 'lifelineDashed', '1') == '1');
            c.begin();
            c.moveTo(x + w / 2, y + size);
            c.lineTo(x + w / 2, y + h);
            c.end();
            c.stroke();
        }
    };
    UmlLifeline.prototype.paintForeground = function (c, x, y, w, h) {
        var size = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        mxRectangleShape.prototype.paintForeground.call(this, c, x, y, w, Math.min(h, size));
    };

    mxCellRenderer.registerShape('umlLifeline', UmlLifeline);

    // UML Frame Shape
    function UmlFrame() {
        mxShape.call(this);
    };
    mxUtils.extend(UmlFrame, mxShape);
    UmlFrame.prototype.width = 60;
    UmlFrame.prototype.height = 30;
    UmlFrame.prototype.corner = 10;
    UmlFrame.prototype.getLabelMargins = function (rect) {
        return new mxRectangle(0, 0,
            rect.width - (parseFloat(mxUtils.getValue(this.style, 'width', this.width) * this.scale)),
            rect.height - (parseFloat(mxUtils.getValue(this.style, 'height', this.height) * this.scale)));
    };
    UmlFrame.prototype.paintBackground = function (c, x, y, w, h) {
        var co = this.corner;
        var w0 = Math.min(w, Math.max(co, parseFloat(mxUtils.getValue(this.style, 'width', this.width))));
        var h0 = Math.min(h, Math.max(co * 1.5, parseFloat(mxUtils.getValue(this.style, 'height', this.height))));
        var bg = mxUtils.getValue(this.style, mxConstants.STYLE_SWIMLANE_FILLCOLOR, mxConstants.NONE);

        if (bg != mxConstants.NONE) {
            c.setFillColor(bg);
            c.rect(x, y, w, h);
            c.fill();
        }

        if (this.fill != null && this.fill != mxConstants.NONE && this.gradient && this.gradient != mxConstants.NONE) {
            var b = this.getGradientBounds(c, x, y, w, h);
            c.setGradient(this.fill, this.gradient, x, y, w, h, this.gradientDirection);
        } else {
            c.setFillColor(this.fill);
        }

        c.begin();
        c.moveTo(x, y);
        c.lineTo(x + w0, y);
        c.lineTo(x + w0, y + Math.max(0, h0 - co * 1.5));
        c.lineTo(x + Math.max(0, w0 - co), y + h0);
        c.lineTo(x, y + h0);
        c.close();
        c.fillAndStroke();

        c.begin();
        c.moveTo(x + w0, y);
        c.lineTo(x + w, y);
        c.lineTo(x + w, y + h);
        c.lineTo(x, y + h);
        c.lineTo(x, y + h0);
        c.stroke();
    };

    mxCellRenderer.registerShape('umlFrame', UmlFrame);
    window.UmlFrame = UmlFrame
    mxPerimeter.LifelinePerimeter = function (bounds, vertex, next, orthogonal) {
        var size = UmlLifeline.prototype.size;

        if (vertex != null) {
            size = mxUtils.getValue(vertex.style, 'size', size) * vertex.view.scale;
        }

        var sw = (parseFloat(vertex.style[mxConstants.STYLE_STROKEWIDTH] || 1) * vertex.view.scale / 2) - 1;

        if (next.x < bounds.getCenterX()) {
            sw += 1;
            sw *= -1;
        }

        return new mxPoint(bounds.getCenterX() + sw, Math.min(bounds.y + bounds.height,
            Math.max(bounds.y + size, next.y)));
    };

    mxStyleRegistry.putValue('lifelinePerimeter', mxPerimeter.LifelinePerimeter);

    mxPerimeter.OrthogonalPerimeter = function (bounds, vertex, next, orthogonal) {
        orthogonal = true;

        return mxPerimeter.RectanglePerimeter.apply(this, arguments);
    };

    mxStyleRegistry.putValue('orthogonalPerimeter', mxPerimeter.OrthogonalPerimeter);

    mxPerimeter.BackbonePerimeter = function (bounds, vertex, next, orthogonal) {
        var sw = (parseFloat(vertex.style[mxConstants.STYLE_STROKEWIDTH] || 1) * vertex.view.scale / 2) - 1;

        if (vertex.style['backboneSize'] != null) {
            sw += (parseFloat(vertex.style['backboneSize']) * vertex.view.scale / 2) - 1;
        }

        if (vertex.style[mxConstants.STYLE_DIRECTION] == 'south' ||
            vertex.style[mxConstants.STYLE_DIRECTION] == 'north') {
            if (next.x < bounds.getCenterX()) {
                sw += 1;
                sw *= -1;
            }

            return new mxPoint(bounds.getCenterX() + sw, Math.min(bounds.y + bounds.height,
                Math.max(bounds.y, next.y)));
        } else {
            if (next.y < bounds.getCenterY()) {
                sw += 1;
                sw *= -1;
            }

            return new mxPoint(Math.min(bounds.x + bounds.width, Math.max(bounds.x, next.x)),
                bounds.getCenterY() + sw);
        }
    };

    mxStyleRegistry.putValue('backbonePerimeter', mxPerimeter.BackbonePerimeter);

    // Callout Perimeter
    mxPerimeter.CalloutPerimeter = function (bounds, vertex, next, orthogonal) {
        return mxPerimeter.RectanglePerimeter(mxUtils.getDirectedBounds(bounds, new mxRectangle(0, 0, 0,
            Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(vertex.style, 'size',
                CalloutShape.prototype.size)) * vertex.view.scale))),
            vertex.style), vertex, next, orthogonal);
    };

    mxStyleRegistry.putValue('calloutPerimeter', mxPerimeter.CalloutPerimeter);

    // Parallelogram Perimeter
    mxPerimeter.ParallelogramPerimeter = function (bounds, vertex, next, orthogonal) {
        var fixed = mxUtils.getValue(vertex.style, 'fixedSize', '0') != '0';
        var size = (fixed) ? ParallelogramShape.prototype.fixedSize : ParallelogramShape.prototype.size;

        if (vertex != null) {
            size = mxUtils.getValue(vertex.style, 'size', size);
        }

        if (fixed) {
            size *= vertex.view.scale;
        }

        var x = bounds.x;
        var y = bounds.y;
        var w = bounds.width;
        var h = bounds.height;

        var direction = (vertex != null) ? mxUtils.getValue(
            vertex.style, mxConstants.STYLE_DIRECTION,
            mxConstants.DIRECTION_EAST) : mxConstants.DIRECTION_EAST;
        var vertical = direction == mxConstants.DIRECTION_NORTH ||
            direction == mxConstants.DIRECTION_SOUTH;
        var points;

        if (vertical) {
            var dy = (fixed) ? Math.max(0, Math.min(h, size)) : h * Math.max(0, Math.min(1, size));
            points = [new mxPoint(x, y), new mxPoint(x + w, y + dy),
                new mxPoint(x + w, y + h), new mxPoint(x, y + h - dy), new mxPoint(x, y)];
        } else {
            var dx = (fixed) ? Math.max(0, Math.min(w * 0.5, size)) : w * Math.max(0, Math.min(1, size));
            points = [new mxPoint(x + dx, y), new mxPoint(x + w, y),
                new mxPoint(x + w - dx, y + h), new mxPoint(x, y + h), new mxPoint(x + dx, y)];
        }

        var cx = bounds.getCenterX();
        var cy = bounds.getCenterY();

        var p1 = new mxPoint(cx, cy);

        if (orthogonal) {
            if (next.x < x || next.x > x + w) {
                p1.y = next.y;
            } else {
                p1.x = next.x;
            }
        }

        return mxUtils.getPerimeterPoint(points, p1, next);
    };

    mxStyleRegistry.putValue('parallelogramPerimeter', mxPerimeter.ParallelogramPerimeter);

    // Trapezoid Perimeter
    mxPerimeter.TrapezoidPerimeter = function (bounds, vertex, next, orthogonal) {
        var fixed = mxUtils.getValue(vertex.style, 'fixedSize', '0') != '0';
        var size = (fixed) ? TrapezoidShape.prototype.fixedSize : TrapezoidShape.prototype.size;

        if (vertex != null) {
            size = mxUtils.getValue(vertex.style, 'size', size);
        }

        if (fixed) {
            size *= vertex.view.scale;
        }

        var x = bounds.x;
        var y = bounds.y;
        var w = bounds.width;
        var h = bounds.height;

        var direction = (vertex != null) ? mxUtils.getValue(
            vertex.style, mxConstants.STYLE_DIRECTION,
            mxConstants.DIRECTION_EAST) : mxConstants.DIRECTION_EAST;
        var points = [];

        if (direction == mxConstants.DIRECTION_EAST) {
            var dx = (fixed) ? Math.max(0, Math.min(w * 0.5, size)) : w * Math.max(0, Math.min(1, size));
            points = [new mxPoint(x + dx, y), new mxPoint(x + w - dx, y),
                new mxPoint(x + w, y + h), new mxPoint(x, y + h), new mxPoint(x + dx, y)];
        } else if (direction == mxConstants.DIRECTION_WEST) {
            var dx = (fixed) ? Math.max(0, Math.min(w, size)) : w * Math.max(0, Math.min(1, size));
            points = [new mxPoint(x, y), new mxPoint(x + w, y),
                new mxPoint(x + w - dx, y + h), new mxPoint(x + dx, y + h), new mxPoint(x, y)];
        } else if (direction == mxConstants.DIRECTION_NORTH) {
            var dy = (fixed) ? Math.max(0, Math.min(h, size)) : h * Math.max(0, Math.min(1, size));
            points = [new mxPoint(x, y + dy), new mxPoint(x + w, y),
                new mxPoint(x + w, y + h), new mxPoint(x, y + h - dy), new mxPoint(x, y + dy)];
        } else {
            var dy = (fixed) ? Math.max(0, Math.min(h, size)) : h * Math.max(0, Math.min(1, size));
            points = [new mxPoint(x, y), new mxPoint(x + w, y + dy),
                new mxPoint(x + w, y + h - dy), new mxPoint(x, y + h), new mxPoint(x, y)];
        }

        var cx = bounds.getCenterX();
        var cy = bounds.getCenterY();

        var p1 = new mxPoint(cx, cy);

        if (orthogonal) {
            if (next.x < x || next.x > x + w) {
                p1.y = next.y;
            } else {
                p1.x = next.x;
            }
        }

        return mxUtils.getPerimeterPoint(points, p1, next);
    };

    mxStyleRegistry.putValue('trapezoidPerimeter', mxPerimeter.TrapezoidPerimeter);

    // Step Perimeter
    mxPerimeter.StepPerimeter = function (bounds, vertex, next, orthogonal) {
        var fixed = mxUtils.getValue(vertex.style, 'fixedSize', '0') != '0';
        var size = (fixed) ? StepShape.prototype.fixedSize : StepShape.prototype.size;

        if (vertex != null) {
            size = mxUtils.getValue(vertex.style, 'size', size);
        }

        if (fixed) {
            size *= vertex.view.scale;
        }

        var x = bounds.x;
        var y = bounds.y;
        var w = bounds.width;
        var h = bounds.height;

        var cx = bounds.getCenterX();
        var cy = bounds.getCenterY();

        var direction = (vertex != null) ? mxUtils.getValue(
            vertex.style, mxConstants.STYLE_DIRECTION,
            mxConstants.DIRECTION_EAST) : mxConstants.DIRECTION_EAST;
        var points;

        if (direction == mxConstants.DIRECTION_EAST) {
            var dx = (fixed) ? Math.max(0, Math.min(w, size)) : w * Math.max(0, Math.min(1, size));
            points = [new mxPoint(x, y), new mxPoint(x + w - dx, y), new mxPoint(x + w, cy),
                new mxPoint(x + w - dx, y + h), new mxPoint(x, y + h),
                new mxPoint(x + dx, cy), new mxPoint(x, y)];
        } else if (direction == mxConstants.DIRECTION_WEST) {
            var dx = (fixed) ? Math.max(0, Math.min(w, size)) : w * Math.max(0, Math.min(1, size));
            points = [new mxPoint(x + dx, y), new mxPoint(x + w, y), new mxPoint(x + w - dx, cy),
                new mxPoint(x + w, y + h), new mxPoint(x + dx, y + h),
                new mxPoint(x, cy), new mxPoint(x + dx, y)];
        } else if (direction == mxConstants.DIRECTION_NORTH) {
            var dy = (fixed) ? Math.max(0, Math.min(h, size)) : h * Math.max(0, Math.min(1, size));
            points = [new mxPoint(x, y + dy), new mxPoint(cx, y), new mxPoint(x + w, y + dy),
                new mxPoint(x + w, y + h), new mxPoint(cx, y + h - dy),
                new mxPoint(x, y + h), new mxPoint(x, y + dy)];
        } else {
            var dy = (fixed) ? Math.max(0, Math.min(h, size)) : h * Math.max(0, Math.min(1, size));
            points = [new mxPoint(x, y), new mxPoint(cx, y + dy), new mxPoint(x + w, y),
                new mxPoint(x + w, y + h - dy), new mxPoint(cx, y + h),
                new mxPoint(x, y + h - dy), new mxPoint(x, y)];
        }

        var p1 = new mxPoint(cx, cy);

        if (orthogonal) {
            if (next.x < x || next.x > x + w) {
                p1.y = next.y;
            } else {
                p1.x = next.x;
            }
        }

        return mxUtils.getPerimeterPoint(points, p1, next);
    };

    mxStyleRegistry.putValue('stepPerimeter', mxPerimeter.StepPerimeter);

    // Hexagon Perimeter 2 (keep existing one)
    mxPerimeter.HexagonPerimeter2 = function (bounds, vertex, next, orthogonal) {
        var fixed = mxUtils.getValue(vertex.style, 'fixedSize', '0') != '0';
        var size = (fixed) ? HexagonShape.prototype.fixedSize : HexagonShape.prototype.size;

        if (vertex != null) {
            size = mxUtils.getValue(vertex.style, 'size', size);
        }

        if (fixed) {
            size *= vertex.view.scale;
        }

        var x = bounds.x;
        var y = bounds.y;
        var w = bounds.width;
        var h = bounds.height;

        var cx = bounds.getCenterX();
        var cy = bounds.getCenterY();

        var direction = (vertex != null) ? mxUtils.getValue(
            vertex.style, mxConstants.STYLE_DIRECTION,
            mxConstants.DIRECTION_EAST) : mxConstants.DIRECTION_EAST;
        var vertical = direction == mxConstants.DIRECTION_NORTH ||
            direction == mxConstants.DIRECTION_SOUTH;
        var points;

        if (vertical) {
            var dy = (fixed) ? Math.max(0, Math.min(h, size)) : h * Math.max(0, Math.min(1, size));
            points = [new mxPoint(cx, y), new mxPoint(x + w, y + dy), new mxPoint(x + w, y + h - dy),
                new mxPoint(cx, y + h), new mxPoint(x, y + h - dy),
                new mxPoint(x, y + dy), new mxPoint(cx, y)];
        } else {
            var dx = (fixed) ? Math.max(0, Math.min(w, size)) : w * Math.max(0, Math.min(1, size));
            points = [new mxPoint(x + dx, y), new mxPoint(x + w - dx, y), new mxPoint(x + w, cy),
                new mxPoint(x + w - dx, y + h), new mxPoint(x + dx, y + h),
                new mxPoint(x, cy), new mxPoint(x + dx, y)];
        }

        var p1 = new mxPoint(cx, cy);

        if (orthogonal) {
            if (next.x < x || next.x > x + w) {
                p1.y = next.y;
            } else {
                p1.x = next.x;
            }
        }

        return mxUtils.getPerimeterPoint(points, p1, next);
    };

    mxStyleRegistry.putValue('hexagonPerimeter2', mxPerimeter.HexagonPerimeter2);

    // Provided Interface Shape (aka Lollipop)
    function LollipopShape() {
        mxShape.call(this);
    };
    mxUtils.extend(LollipopShape, mxShape);
    LollipopShape.prototype.size = 10;
    LollipopShape.prototype.paintBackground = function (c, x, y, w, h) {
        var sz = parseFloat(mxUtils.getValue(this.style, 'size', this.size));
        c.translate(x, y);

        c.ellipse((w - sz) / 2, 0, sz, sz);
        c.fillAndStroke();

        c.begin();
        c.moveTo(w / 2, sz);
        c.lineTo(w / 2, h);
        c.end();
        c.stroke();
    };

    mxCellRenderer.registerShape('lollipop', LollipopShape);

    // Required Interface Shape
    function RequiresShape() {
        mxShape.call(this);
    };
    mxUtils.extend(RequiresShape, mxShape);
    RequiresShape.prototype.size = 10;
    RequiresShape.prototype.inset = 2;
    RequiresShape.prototype.paintBackground = function (c, x, y, w, h) {
        var sz = parseFloat(mxUtils.getValue(this.style, 'size', this.size));
        var inset = parseFloat(mxUtils.getValue(this.style, 'inset', this.inset)) + this.strokewidth;
        c.translate(x, y);

        c.begin();
        c.moveTo(w / 2, sz + inset);
        c.lineTo(w / 2, h);
        c.end();
        c.stroke();

        c.begin();
        c.moveTo((w - sz) / 2 - inset, sz / 2);
        c.quadTo((w - sz) / 2 - inset, sz + inset, w / 2, sz + inset);
        c.quadTo((w + sz) / 2 + inset, sz + inset, (w + sz) / 2 + inset, sz / 2);
        c.end();
        c.stroke();
    };

    mxCellRenderer.registerShape('requires', RequiresShape);

    // Required Interface Shape
    function RequiredInterfaceShape() {
        mxShape.call(this);
    };
    mxUtils.extend(RequiredInterfaceShape, mxShape);

    RequiredInterfaceShape.prototype.paintBackground = function (c, x, y, w, h) {
        c.translate(x, y);

        c.begin();
        c.moveTo(0, 0);
        c.quadTo(w, 0, w, h / 2);
        c.quadTo(w, h, 0, h);
        c.end();
        c.stroke();
    };

    mxCellRenderer.registerShape('requiredInterface', RequiredInterfaceShape);

    // Provided and Required Interface Shape
    function ProvidedRequiredInterfaceShape() {
        mxShape.call(this);
    };
    mxUtils.extend(ProvidedRequiredInterfaceShape, mxShape);
    ProvidedRequiredInterfaceShape.prototype.inset = 2;
    ProvidedRequiredInterfaceShape.prototype.paintBackground = function (c, x, y, w, h) {
        var inset = parseFloat(mxUtils.getValue(this.style, 'inset', this.inset)) + this.strokewidth;
        c.translate(x, y);

        c.ellipse(0, inset, w - 2 * inset, h - 2 * inset);
        c.fillAndStroke();

        c.begin();
        c.moveTo(w / 2, 0);
        c.quadTo(w, 0, w, h / 2);
        c.quadTo(w, h, w / 2, h);
        c.end();
        c.stroke();
    };

    mxCellRenderer.registerShape('providedRequiredInterface', ProvidedRequiredInterfaceShape);

    // Module shape
    function ModuleShape() {
        mxCylinder.call(this);
    };
    mxUtils.extend(ModuleShape, mxCylinder);
    ModuleShape.prototype.jettyWidth = 20;
    ModuleShape.prototype.jettyHeight = 10;
    ModuleShape.prototype.redrawPath = function (path, x, y, w, h, isForeground) {
        var dx = parseFloat(mxUtils.getValue(this.style, 'jettyWidth', this.jettyWidth));
        var dy = parseFloat(mxUtils.getValue(this.style, 'jettyHeight', this.jettyHeight));
        var x0 = dx / 2;
        var x1 = x0 + dx / 2;
        var y0 = Math.min(dy, h - dy);
        var y1 = Math.min(y0 + 2 * dy, h - dy);

        if (isForeground) {
            path.moveTo(x0, y0);
            path.lineTo(x1, y0);
            path.lineTo(x1, y0 + dy);
            path.lineTo(x0, y0 + dy);
            path.moveTo(x0, y1);
            path.lineTo(x1, y1);
            path.lineTo(x1, y1 + dy);
            path.lineTo(x0, y1 + dy);
            path.end();
        } else {
            path.moveTo(x0, 0);
            path.lineTo(w, 0);
            path.lineTo(w, h);
            path.lineTo(x0, h);
            path.lineTo(x0, y1 + dy);
            path.lineTo(0, y1 + dy);
            path.lineTo(0, y1);
            path.lineTo(x0, y1);
            path.lineTo(x0, y0 + dy);
            path.lineTo(0, y0 + dy);
            path.lineTo(0, y0);
            path.lineTo(x0, y0);
            path.close();
            path.end();
        }
    };

    mxCellRenderer.registerShape('module', ModuleShape);

    // Component shape
    function ComponentShape() {
        mxCylinder.call(this);
    };
    mxUtils.extend(ComponentShape, mxCylinder);
    ComponentShape.prototype.jettyWidth = 32;
    ComponentShape.prototype.jettyHeight = 12;
    ComponentShape.prototype.redrawPath = function (path, x, y, w, h, isForeground) {
        var dx = parseFloat(mxUtils.getValue(this.style, 'jettyWidth', this.jettyWidth));
        var dy = parseFloat(mxUtils.getValue(this.style, 'jettyHeight', this.jettyHeight));
        var x0 = dx / 2;
        var x1 = x0 + dx / 2;
        var y0 = 0.3 * h - dy / 2;
        var y1 = 0.7 * h - dy / 2;

        if (isForeground) {
            path.moveTo(x0, y0);
            path.lineTo(x1, y0);
            path.lineTo(x1, y0 + dy);
            path.lineTo(x0, y0 + dy);
            path.moveTo(x0, y1);
            path.lineTo(x1, y1);
            path.lineTo(x1, y1 + dy);
            path.lineTo(x0, y1 + dy);
            path.end();
        } else {
            path.moveTo(x0, 0);
            path.lineTo(w, 0);
            path.lineTo(w, h);
            path.lineTo(x0, h);
            path.lineTo(x0, y1 + dy);
            path.lineTo(0, y1 + dy);
            path.lineTo(0, y1);
            path.lineTo(x0, y1);
            path.lineTo(x0, y0 + dy);
            path.lineTo(0, y0 + dy);
            path.lineTo(0, y0);
            path.lineTo(x0, y0);
            path.close();
            path.end();
        }
    };

    mxCellRenderer.registerShape('component', ComponentShape);

    // Associative entity derived from rectangle shape
    function AssociativeEntity() {
        mxRectangleShape.call(this);
    };
    mxUtils.extend(AssociativeEntity, mxRectangleShape);
    AssociativeEntity.prototype.paintForeground = function (c, x, y, w, h) {
        var hw = w / 2;
        var hh = h / 2;

        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        c.begin();
        this.addPoints(c, [new mxPoint(x + hw, y), new mxPoint(x + w, y + hh), new mxPoint(x + hw, y + h),
            new mxPoint(x, y + hh)], this.isRounded, arcSize, true);
        c.stroke();

        mxRectangleShape.prototype.paintForeground.apply(this, arguments);
    };

    mxCellRenderer.registerShape('associativeEntity', AssociativeEntity);

    // State Shapes derives from double ellipse
    function StateShape() {
        mxDoubleEllipse.call(this);
    };
    mxUtils.extend(StateShape, mxDoubleEllipse);
    StateShape.prototype.outerStroke = true;
    StateShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        var inset = Math.min(4, Math.min(w / 5, h / 5));

        if (w > 0 && h > 0) {
            c.ellipse(x + inset, y + inset, w - 2 * inset, h - 2 * inset);
            c.fillAndStroke();
        }

        c.setShadow(false);

        if (this.outerStroke) {
            c.ellipse(x, y, w, h);
            c.stroke();
        }
    };

    mxCellRenderer.registerShape('endState', StateShape);

    function StartStateShape() {
        StateShape.call(this);
    };
    mxUtils.extend(StartStateShape, StateShape);
    StartStateShape.prototype.outerStroke = false;

    mxCellRenderer.registerShape('startState', StartStateShape);

    // Link shape
    function LinkShape() {
        mxArrowConnector.call(this);
        this.spacing = 0;
    };
    mxUtils.extend(LinkShape, mxArrowConnector);
    LinkShape.prototype.defaultWidth = 4;

    LinkShape.prototype.isOpenEnded = function () {
        return true;
    };

    LinkShape.prototype.getEdgeWidth = function () {
        return mxUtils.getNumber(this.style, 'width', this.defaultWidth) + Math.max(0, this.strokewidth - 1);
    };

    LinkShape.prototype.isArrowRounded = function () {
        return this.isRounded;
    };

    // Registers the link shape
    mxCellRenderer.registerShape('link', LinkShape);

    // Generic arrow
    function FlexArrowShape() {
        mxArrowConnector.call(this);
        this.spacing = 0;
    };
    mxUtils.extend(FlexArrowShape, mxArrowConnector);
    FlexArrowShape.prototype.defaultWidth = 10;
    FlexArrowShape.prototype.defaultArrowWidth = 20;

    FlexArrowShape.prototype.getStartArrowWidth = function () {
        return this.getEdgeWidth() + mxUtils.getNumber(this.style, 'startWidth', this.defaultArrowWidth);
    };

    FlexArrowShape.prototype.getEndArrowWidth = function () {
        return this.getEdgeWidth() + mxUtils.getNumber(this.style, 'endWidth', this.defaultArrowWidth);
        ;
    };

    FlexArrowShape.prototype.getEdgeWidth = function () {
        return mxUtils.getNumber(this.style, 'width', this.defaultWidth) + Math.max(0, this.strokewidth - 1);
    };

    // Registers the link shape
    mxCellRenderer.registerShape('flexArrow', FlexArrowShape);

    // Manual Input shape
    function ManualInputShape() {
        mxActor.call(this);
    };
    mxUtils.extend(ManualInputShape, mxActor);
    ManualInputShape.prototype.size = 30;
    ManualInputShape.prototype.isRoundable = function () {
        return true;
    };
    ManualInputShape.prototype.redrawPath = function (c, x, y, w, h) {
        var s = Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size)));
        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        this.addPoints(c, [new mxPoint(0, h), new mxPoint(0, s), new mxPoint(w, 0), new mxPoint(w, h)],
            this.isRounded, arcSize, true);
        c.end();
    };

    mxCellRenderer.registerShape('manualInput', ManualInputShape);

    // Internal storage
    function InternalStorageShape() {
        mxRectangleShape.call(this);
    };
    mxUtils.extend(InternalStorageShape, mxRectangleShape);
    InternalStorageShape.prototype.dx = 20;
    InternalStorageShape.prototype.dy = 20;
    InternalStorageShape.prototype.isHtmlAllowed = function () {
        return false;
    };
    InternalStorageShape.prototype.paintForeground = function (c, x, y, w, h) {
        mxRectangleShape.prototype.paintForeground.apply(this, arguments);
        var inset = 0;

        if (this.isRounded) {
            var f = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE,
                mxConstants.RECTANGLE_ROUNDING_FACTOR * 100) / 100;
            inset = Math.max(inset, Math.min(w * f, h * f));
        }

        var dx = Math.max(inset, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
        var dy = Math.max(inset, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));

        c.begin();
        c.moveTo(x, y + dy);
        c.lineTo(x + w, y + dy);
        c.end();
        c.stroke();

        c.begin();
        c.moveTo(x + dx, y);
        c.lineTo(x + dx, y + h);
        c.end();
        c.stroke();
    };

    mxCellRenderer.registerShape('internalStorage', InternalStorageShape);

    // Internal storage
    function CornerShape() {
        mxActor.call(this);
    };
    mxUtils.extend(CornerShape, mxActor);
    CornerShape.prototype.dx = 20;
    CornerShape.prototype.dy = 20;

    // Corner
    CornerShape.prototype.redrawPath = function (c, x, y, w, h) {
        var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
        var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));

        var s = Math.min(w / 2, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        this.addPoints(c, [new mxPoint(0, 0), new mxPoint(w, 0), new mxPoint(w, dy), new mxPoint(dx, dy),
            new mxPoint(dx, h), new mxPoint(0, h)], this.isRounded, arcSize, true);
        c.end();
    };

    mxCellRenderer.registerShape('corner', CornerShape);

    // Crossbar shape
    function CrossbarShape() {
        mxActor.call(this);
    };
    mxUtils.extend(CrossbarShape, mxActor);

    CrossbarShape.prototype.redrawPath = function (c, x, y, w, h) {
        c.moveTo(0, 0);
        c.lineTo(0, h);
        c.end();

        c.moveTo(w, 0);
        c.lineTo(w, h);
        c.end();

        c.moveTo(0, h / 2);
        c.lineTo(w, h / 2);
        c.end();
    };

    mxCellRenderer.registerShape('crossbar', CrossbarShape);
      
    // 倒T shape
    function DownTShape() {
        mxActor.call(this);
    };
    mxUtils.extend(DownTShape, mxActor);

    DownTShape.prototype.redrawPath = function (c, x, y, w, h) {
        c.moveTo(0, h);
        c.lineTo(w, h);
        c.end();

        c.moveTo(w / 2, 0);
        c.lineTo(w / 2, h);
        c.end();
    };

    mxCellRenderer.registerShape('downT', DownTShape);

    // 正T shape
    function UpwardsTShape() {
        mxActor.call(this);
    };
    mxUtils.extend(UpwardsTShape, mxActor);

    UpwardsTShape.prototype.redrawPath = function (c, x, y, w, h) {
        c.moveTo(0, 0);
        c.lineTo(w, 0);
        c.end();

        c.moveTo(w / 2, 0);
        c.lineTo(w / 2, h);
        c.end();
    };

    mxCellRenderer.registerShape('upwardsT', UpwardsTShape);

    // 带六边形的矩形
    function HexagonalRectShape() {
        mxActor.call(this);
    };
    mxUtils.extend(HexagonalRectShape, mxActor);

    HexagonalRectShape.prototype.redrawPath = function (c, x, y, w, h) {
        const sortLine = h / 4
        const offset = Math.sqrt(2 * sortLine) / 2
        c.moveTo(0, 0);
        c.lineTo(0, 0);
        c.lineTo(w, 0);
        c.lineTo(w, h);
        c.lineTo(0, h);
        c.lineTo(0, 0);
        c.end();
        // // 以下的逻辑是画一个正六边形
        // c.moveTo(-sortLine * 0.5, sortLine);
        // c.lineTo(sortLine * 0.5, sortLine);
        // c.lineTo(sortLine + offset, 2 * sortLine);
        // c.lineTo(sortLine * 0.5, 3 * sortLine);
        // c.lineTo(-sortLine * 0.5, 3 * sortLine);
        // c.lineTo(-(sortLine + offset), 2 * sortLine);
        // c.lineTo(-sortLine * 0.5, sortLine);
        // c.end();
        return
        setTimeout(() => {
            const size = 50
            // 前四个参数：x偏移量 y偏移量 宽 高
            c.image(-size / 2, (h - size) / 2 , size, size, 'images/六边形.svg', false, false, false)
        }, 0);
    };

    // 自定义文字的显示位置，在左侧边上
    HexagonalRectShape.prototype.getLabelBounds = function(rect) {
        const newRect = new mxRectangle(rect.x - rect.width / 2, rect.y,
            rect.width, rect.height);
        return newRect
    }

    mxCellRenderer.registerShape('hexagonalRect', HexagonalRectShape);

    // Internal storage
    function TeeShape() {
        mxActor.call(this);
    };
    mxUtils.extend(TeeShape, mxActor);
    TeeShape.prototype.dx = 20;
    TeeShape.prototype.dy = 20;

    // Corner
    TeeShape.prototype.redrawPath = function (c, x, y, w, h) {
        var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
        var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
        var w2 = Math.abs(w - dx) / 2;

        var s = Math.min(w / 2, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        this.addPoints(c, [new mxPoint(0, 0), new mxPoint(w, 0), new mxPoint(w, dy), new mxPoint((w + dx) / 2, dy),
            new mxPoint((w + dx) / 2, h), new mxPoint((w - dx) / 2, h), new mxPoint((w - dx) / 2, dy),
            new mxPoint(0, dy)], this.isRounded, arcSize, true);
        c.end();
    };

    mxCellRenderer.registerShape('tee', TeeShape);

    // Arrow
    function SingleArrowShape() {
        mxActor.call(this);
    };
    mxUtils.extend(SingleArrowShape, mxActor);
    SingleArrowShape.prototype.arrowWidth = 0.3;
    SingleArrowShape.prototype.arrowSize = 0.2;
    SingleArrowShape.prototype.redrawPath = function (c, x, y, w, h) {
        var aw = h * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'arrowWidth', this.arrowWidth))));
        var as = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'arrowSize', this.arrowSize))));
        var at = (h - aw) / 2;
        var ab = at + aw;

        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        this.addPoints(c, [new mxPoint(0, at), new mxPoint(w - as, at), new mxPoint(w - as, 0), new mxPoint(w, h / 2),
                new mxPoint(w - as, h), new mxPoint(w - as, ab), new mxPoint(0, ab)],
            this.isRounded, arcSize, true);
        c.end();
    };

    mxCellRenderer.registerShape('singleArrow', SingleArrowShape);

    // Arrow
    function DoubleArrowShape() {
        mxActor.call(this);
    };
    mxUtils.extend(DoubleArrowShape, mxActor);
    DoubleArrowShape.prototype.redrawPath = function (c, x, y, w, h) {
        var aw = h * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'arrowWidth', SingleArrowShape.prototype.arrowWidth))));
        var as = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'arrowSize', SingleArrowShape.prototype.arrowSize))));
        var at = (h - aw) / 2;
        var ab = at + aw;

        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        this.addPoints(c, [new mxPoint(0, h / 2), new mxPoint(as, 0), new mxPoint(as, at), new mxPoint(w - as, at),
                new mxPoint(w - as, 0), new mxPoint(w, h / 2), new mxPoint(w - as, h),
                new mxPoint(w - as, ab), new mxPoint(as, ab), new mxPoint(as, h)],
            this.isRounded, arcSize, true);
        c.end();
    };

    mxCellRenderer.registerShape('doubleArrow', DoubleArrowShape);

    // Data storage
    function DataStorageShape() {
        mxActor.call(this);
    };
    mxUtils.extend(DataStorageShape, mxActor);
    DataStorageShape.prototype.size = 0.1;
    DataStorageShape.prototype.fixedSize = 20;
    DataStorageShape.prototype.redrawPath = function (c, x, y, w, h) {
        var fixed = mxUtils.getValue(this.style, 'fixedSize', '0') != '0';
        var s = (fixed) ? Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'size', this.fixedSize)))) :
            w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));

        c.moveTo(s, 0);
        c.lineTo(w, 0);
        c.quadTo(w - s * 2, h / 2, w, h);
        c.lineTo(s, h);
        c.quadTo(s - s * 2, h / 2, s, 0);
        c.close();
        c.end();
    };

    mxCellRenderer.registerShape('dataStorage', DataStorageShape);

    // Or
    function OrShape() {
        mxActor.call(this);
    };
    mxUtils.extend(OrShape, mxActor);
    OrShape.prototype.redrawPath = function (c, x, y, w, h) {
        c.moveTo(0, 0);
        c.quadTo(w, 0, w, h / 2);
        c.quadTo(w, h, 0, h);
        c.close();
        c.end();
    };

    mxCellRenderer.registerShape('or', OrShape);

    // Xor
    function XorShape() {
        mxActor.call(this);
    };
    mxUtils.extend(XorShape, mxActor);
    XorShape.prototype.redrawPath = function (c, x, y, w, h) {
        c.moveTo(0, 0);
        c.quadTo(w, 0, w, h / 2);
        c.quadTo(w, h, 0, h);
        c.quadTo(w / 2, h / 2, 0, 0);
        c.close();
        c.end();
    };

    mxCellRenderer.registerShape('xor', XorShape);

    // Loop limit
    function LoopLimitShape() {
        mxActor.call(this);
    };
    mxUtils.extend(LoopLimitShape, mxActor);
    LoopLimitShape.prototype.size = 20;
    LoopLimitShape.prototype.isRoundable = function () {
        return true;
    };
    LoopLimitShape.prototype.redrawPath = function (c, x, y, w, h) {
        var s = Math.min(w / 2, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        this.addPoints(c, [new mxPoint(s, 0), new mxPoint(w - s, 0), new mxPoint(w, s * 0.8), new mxPoint(w, h),
            new mxPoint(0, h), new mxPoint(0, s * 0.8)], this.isRounded, arcSize, true);
        c.end();
    };

    mxCellRenderer.registerShape('loopLimit', LoopLimitShape);

    // Off page connector
    function OffPageConnectorShape() {
        mxActor.call(this);
    };
    mxUtils.extend(OffPageConnectorShape, mxActor);
    OffPageConnectorShape.prototype.size = 3 / 8;
    OffPageConnectorShape.prototype.isRoundable = function () {
        return true;
    };
    OffPageConnectorShape.prototype.redrawPath = function (c, x, y, w, h) {
        var s = h * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        this.addPoints(c, [new mxPoint(0, 0), new mxPoint(w, 0), new mxPoint(w, h - s), new mxPoint(w / 2, h),
            new mxPoint(0, h - s)], this.isRounded, arcSize, true);
        c.end();
    };

    mxCellRenderer.registerShape('offPageConnector', OffPageConnectorShape);

    // Internal storage
    function TapeDataShape() {
        mxEllipse.call(this);
    };
    mxUtils.extend(TapeDataShape, mxEllipse);
    TapeDataShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        mxEllipse.prototype.paintVertexShape.apply(this, arguments);

        c.begin();
        c.moveTo(x + w / 2, y + h);
        c.lineTo(x + w, y + h);
        c.end();
        c.stroke();
    };

    mxCellRenderer.registerShape('tapeData', TapeDataShape);

    // OrEllipseShape
    function OrEllipseShape() {
        mxEllipse.call(this);
    };
    mxUtils.extend(OrEllipseShape, mxEllipse);
    OrEllipseShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        mxEllipse.prototype.paintVertexShape.apply(this, arguments);

        c.setShadow(false);
        c.begin();
        c.moveTo(x, y + h / 2);
        c.lineTo(x + w, y + h / 2);
        c.end();
        c.stroke();

        c.begin();
        c.moveTo(x + w / 2, y);
        c.lineTo(x + w / 2, y + h);
        c.end();
        c.stroke();
    };

    mxCellRenderer.registerShape('orEllipse', OrEllipseShape);

    // SumEllipseShape
    function SumEllipseShape() {
        mxEllipse.call(this);
    };
    mxUtils.extend(SumEllipseShape, mxEllipse);
    SumEllipseShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        mxEllipse.prototype.paintVertexShape.apply(this, arguments);
        var s2 = 0.145;

        c.setShadow(false);
        c.begin();
        c.moveTo(x + w * s2, y + h * s2);
        c.lineTo(x + w * (1 - s2), y + h * (1 - s2));
        c.end();
        c.stroke();

        c.begin();
        c.moveTo(x + w * (1 - s2), y + h * s2);
        c.lineTo(x + w * s2, y + h * (1 - s2));
        c.end();
        c.stroke();
    };

    mxCellRenderer.registerShape('sumEllipse', SumEllipseShape);

    // SortShape
    function SortShape() {
        mxRhombus.call(this);
    };
    mxUtils.extend(SortShape, mxRhombus);
    SortShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        mxRhombus.prototype.paintVertexShape.apply(this, arguments);

        c.setShadow(false);
        c.begin();
        c.moveTo(x, y + h / 2);
        c.lineTo(x + w, y + h / 2);
        c.end();
        c.stroke();
    };

    mxCellRenderer.registerShape('sortShape', SortShape);

    // CollateShape
    function CollateShape() {
        mxEllipse.call(this);
    };
    mxUtils.extend(CollateShape, mxEllipse);
    CollateShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        c.begin();
        c.moveTo(x, y);
        c.lineTo(x + w, y);
        c.lineTo(x + w / 2, y + h / 2);
        c.close();
        c.fillAndStroke();

        c.begin();
        c.moveTo(x, y + h);
        c.lineTo(x + w, y + h);
        c.lineTo(x + w / 2, y + h / 2);
        c.close();
        c.fillAndStroke();
    };

    mxCellRenderer.registerShape('collate', CollateShape);

    // DimensionShape
    function DimensionShape() {
        mxEllipse.call(this);
    };
    mxUtils.extend(DimensionShape, mxEllipse);
    DimensionShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        // Arrow size
        var al = 10;
        var cy = y + h - al / 2;

        c.begin();
        c.moveTo(x, y);
        c.lineTo(x, y + h);
        c.moveTo(x, cy);
        c.lineTo(x + al, cy - al / 2);
        c.moveTo(x, cy);
        c.lineTo(x + al, cy + al / 2);
        c.moveTo(x, cy);
        c.lineTo(x + w, cy);

        // Opposite side
        c.moveTo(x + w, y);
        c.lineTo(x + w, y + h);
        c.moveTo(x + w, cy);
        c.lineTo(x + w - al, cy - al / 2);
        c.moveTo(x + w, cy);
        c.lineTo(x + w - al, cy + al / 2);
        c.end();
        c.stroke();
    };

    mxCellRenderer.registerShape('dimension', DimensionShape);

    // PartialRectangleShape
    function PartialRectangleShape() {
        mxEllipse.call(this);
    };
    mxUtils.extend(PartialRectangleShape, mxEllipse);
    PartialRectangleShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        if (!this.outline) {
            c.setStrokeColor(null);
        }

        if (this.style != null) {
            var pointerEvents = c.pointerEvents;
            var events = mxUtils.getValue(this.style, mxConstants.STYLE_POINTER_EVENTS, '1') == '1';

            if (!events && (this.fill == null || this.fill == mxConstants.NONE)) {
                c.pointerEvents = false;
            }

            c.rect(x, y, w, h);
            c.fill();

            c.pointerEvents = pointerEvents;
            c.setStrokeColor(this.stroke);
            c.begin();
            c.moveTo(x, y);

            if (this.outline || mxUtils.getValue(this.style, 'top', '1') == '1') {
                c.lineTo(x + w, y);
            } else {
                c.moveTo(x + w, y);
            }

            if (this.outline || mxUtils.getValue(this.style, 'right', '1') == '1') {
                c.lineTo(x + w, y + h);
            } else {
                c.moveTo(x + w, y + h);
            }

            if (this.outline || mxUtils.getValue(this.style, 'bottom', '1') == '1') {
                c.lineTo(x, y + h);
            } else {
                c.moveTo(x, y + h);
            }

            if (this.outline || mxUtils.getValue(this.style, 'left', '1') == '1') {
                c.lineTo(x, y);
            }

            c.end();
            c.stroke();
        }
    };

    mxCellRenderer.registerShape('partialRectangle', PartialRectangleShape);

    // LineEllipseShape
    function LineEllipseShape() {
        mxEllipse.call(this);
    };
    mxUtils.extend(LineEllipseShape, mxEllipse);
    LineEllipseShape.prototype.paintVertexShape = function (c, x, y, w, h) {
        mxEllipse.prototype.paintVertexShape.apply(this, arguments);

        c.setShadow(false);
        c.begin();

        if (mxUtils.getValue(this.style, 'line') == 'vertical') {
            c.moveTo(x + w / 2, y);
            c.lineTo(x + w / 2, y + h);
        } else {
            c.moveTo(x, y + h / 2);
            c.lineTo(x + w, y + h / 2);
        }

        c.end();
        c.stroke();
    };

    mxCellRenderer.registerShape('lineEllipse', LineEllipseShape);

    // Delay
    function DelayShape() {
        mxActor.call(this);
    };
    mxUtils.extend(DelayShape, mxActor);
    DelayShape.prototype.redrawPath = function (c, x, y, w, h) {
        var dx = Math.min(w, h / 2);
        c.moveTo(0, 0);
        c.lineTo(w - dx, 0);
        c.quadTo(w, 0, w, h / 2);
        c.quadTo(w, h, w - dx, h);
        c.lineTo(0, h);
        c.close();
        c.end();
    };

    mxCellRenderer.registerShape('delay', DelayShape);

    // Cross Shape
    function CrossShape() {
        mxActor.call(this);
    };
    mxUtils.extend(CrossShape, mxActor);
    CrossShape.prototype.size = 0.2;
    CrossShape.prototype.redrawPath = function (c, x, y, w, h) {
        var m = Math.min(h, w);
        var size = Math.max(0, Math.min(m, m * parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var t = (h - size) / 2;
        var b = t + size;
        var l = (w - size) / 2;
        var r = l + size;

        c.moveTo(0, t);
        c.lineTo(l, t);
        c.lineTo(l, 0);
        c.lineTo(r, 0);
        c.lineTo(r, t);
        c.lineTo(w, t);
        c.lineTo(w, b);
        c.lineTo(r, b);
        c.lineTo(r, h);
        c.lineTo(l, h);
        c.lineTo(l, b);
        c.lineTo(0, b);
        c.close();
        c.end();
    };

    mxCellRenderer.registerShape('cross', CrossShape);

    // Display
    function DisplayShape() {
        mxActor.call(this);
    };
    mxUtils.extend(DisplayShape, mxActor);
    DisplayShape.prototype.size = 0.25;
    DisplayShape.prototype.redrawPath = function (c, x, y, w, h) {
        var dx = Math.min(w, h / 2);
        var s = Math.min(w - dx, Math.max(0, parseFloat(mxUtils.getValue(this.style, 'size', this.size))) * w);

        c.moveTo(0, h / 2);
        c.lineTo(s, 0);
        c.lineTo(w - dx, 0);
        c.quadTo(w, 0, w, h / 2);
        c.quadTo(w, h, w - dx, h);
        c.lineTo(s, h);
        c.close();
        c.end();
    };

    mxCellRenderer.registerShape('display', DisplayShape);

    // FilledEdge shape
    function FilledEdge() {
        mxConnector.call(this);
    };
    mxUtils.extend(FilledEdge, mxConnector);

    FilledEdge.prototype.origPaintEdgeShape = FilledEdge.prototype.paintEdgeShape;
    FilledEdge.prototype.paintEdgeShape = function (c, pts, rounded) {
        // Markers modify incoming points array
        var temp = [];

        for (var i = 0; i < pts.length; i++) {
            temp.push(mxUtils.clone(pts[i]));
        }

        // paintEdgeShape resets dashed to false
        var dashed = c.state.dashed;
        var fixDash = c.state.fixDash;
        FilledEdge.prototype.origPaintEdgeShape.apply(this, [c, temp, rounded]);

        if (c.state.strokeWidth >= 3) {
            var fillClr = mxUtils.getValue(this.style, 'fillColor', null);

            if (fillClr != null) {
                c.setStrokeColor(fillClr);
                c.setStrokeWidth(c.state.strokeWidth - 2);
                c.setDashed(dashed, fixDash);

                FilledEdge.prototype.origPaintEdgeShape.apply(this, [c, pts, rounded]);
            }
        }
    };

    // Registers the link shape
    mxCellRenderer.registerShape('filledEdge', FilledEdge);

    // Implements custom colors for shapes
    if (typeof StyleFormatPanel !== 'undefined') {
        (function () {
            var styleFormatPanelGetCustomColors = StyleFormatPanel.prototype.getCustomColors;

            StyleFormatPanel.prototype.getCustomColors = function () {
                var ss = this.format.getSelectionState();
                var result = styleFormatPanelGetCustomColors.apply(this, arguments);

                if (ss.style.shape == 'umlFrame') {
                    result.push({
                        title: mxResources.get('laneColor'),
                        key: 'swimlaneFillColor',
                        defaultValue: '#ffffff'
                    });
                }

                return result;
            };
        })();
    }

    // Registers and defines the custom marker
    mxMarker.addMarker('dash', function (c, shape, type, pe, unitX, unitY, size, source, sw, filled) {
        var nx = unitX * (size + sw + 1);
        var ny = unitY * (size + sw + 1);

        return function () {
            c.begin();
            c.moveTo(pe.x - nx / 2 - ny / 2, pe.y - ny / 2 + nx / 2);
            c.lineTo(pe.x + ny / 2 - 3 * nx / 2, pe.y - 3 * ny / 2 - nx / 2);
            c.stroke();
        };
    });

    // Registers and defines the custom marker
    mxMarker.addMarker('box', function (c, shape, type, pe, unitX, unitY, size, source, sw, filled) {
        var nx = unitX * (size + sw + 1);
        var ny = unitY * (size + sw + 1);
        var px = pe.x + nx / 2;
        var py = pe.y + ny / 2;

        pe.x -= nx;
        pe.y -= ny;

        return function () {
            c.begin();
            c.moveTo(px - nx / 2 - ny / 2, py - ny / 2 + nx / 2);
            c.lineTo(px - nx / 2 + ny / 2, py - ny / 2 - nx / 2);
            c.lineTo(px + ny / 2 - 3 * nx / 2, py - 3 * ny / 2 - nx / 2);
            c.lineTo(px - ny / 2 - 3 * nx / 2, py - 3 * ny / 2 + nx / 2);
            c.close();

            if (filled) {
                c.fillAndStroke();
            } else {
                c.stroke();
            }
        };
    });

    // Registers and defines the custom marker
    mxMarker.addMarker('cross', function (c, shape, type, pe, unitX, unitY, size, source, sw, filled) {
        var nx = unitX * (size + sw + 1);
        var ny = unitY * (size + sw + 1);

        return function () {
            c.begin();
            c.moveTo(pe.x - nx / 2 - ny / 2, pe.y - ny / 2 + nx / 2);
            c.lineTo(pe.x + ny / 2 - 3 * nx / 2, pe.y - 3 * ny / 2 - nx / 2);
            c.moveTo(pe.x - nx / 2 + ny / 2, pe.y - ny / 2 - nx / 2);
            c.lineTo(pe.x - ny / 2 - 3 * nx / 2, pe.y - 3 * ny / 2 + nx / 2);
            c.stroke();
        };
    });

    function circleMarker(c, shape, type, pe, unitX, unitY, size, source, sw, filled) {
        var a = size / 2;
        var size = size + sw;

        var pt = pe.clone();

        pe.x -= unitX * (2 * size + sw);
        pe.y -= unitY * (2 * size + sw);

        unitX = unitX * (size + sw);
        unitY = unitY * (size + sw);

        return function () {
            c.ellipse(pt.x - unitX - size, pt.y - unitY - size, 2 * size, 2 * size);

            if (filled) {
                c.fillAndStroke();
            } else {
                c.stroke();
            }
        };
    };

    mxMarker.addMarker('circle', circleMarker);
    mxMarker.addMarker('circlePlus', function (c, shape, type, pe, unitX, unitY, size, source, sw, filled) {
        var pt = pe.clone();
        var fn = circleMarker.apply(this, arguments);
        var nx = unitX * (size + 2 * sw); // (size + sw + 1);
        var ny = unitY * (size + 2 * sw); //(size + sw + 1);

        return function () {
            fn.apply(this, arguments);

            c.begin();
            c.moveTo(pt.x - unitX * (sw), pt.y - unitY * (sw));
            c.lineTo(pt.x - 2 * nx + unitX * (sw), pt.y - 2 * ny + unitY * (sw));
            c.moveTo(pt.x - nx - ny + unitY * sw, pt.y - ny + nx - unitX * sw);
            c.lineTo(pt.x + ny - nx - unitY * sw, pt.y - ny - nx + unitX * sw);
            c.stroke();
        };
    });

    // Registers and defines the custom marker
    mxMarker.addMarker('halfCircle', function (c, shape, type, pe, unitX, unitY, size, source, sw, filled) {
        var nx = unitX * (size + sw + 1);
        var ny = unitY * (size + sw + 1);
        var pt = pe.clone();

        pe.x -= nx;
        pe.y -= ny;

        return function () {
            c.begin();
            c.moveTo(pt.x - ny, pt.y + nx);
            c.quadTo(pe.x - ny, pe.y + nx, pe.x, pe.y);
            c.quadTo(pe.x + ny, pe.y - nx, pt.x + ny, pt.y - nx);
            c.stroke();
        };
    });

    mxMarker.addMarker('async', function (c, shape, type, pe, unitX, unitY, size, source, sw, filled) {
        // The angle of the forward facing arrow sides against the x axis is
        // 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for
        // only half the strokewidth is processed ).
        var endOffsetX = unitX * sw * 1.118;
        var endOffsetY = unitY * sw * 1.118;

        unitX = unitX * (size + sw);
        unitY = unitY * (size + sw);

        var pt = pe.clone();
        pt.x -= endOffsetX;
        pt.y -= endOffsetY;

        var f = 1;
        pe.x += -unitX * f - endOffsetX;
        pe.y += -unitY * f - endOffsetY;

        return function () {
            c.begin();
            c.moveTo(pt.x, pt.y);

            if (source) {
                c.lineTo(pt.x - unitX - unitY / 2, pt.y - unitY + unitX / 2);
            } else {
                c.lineTo(pt.x + unitY / 2 - unitX, pt.y - unitY - unitX / 2);
            }

            c.lineTo(pt.x - unitX, pt.y - unitY);
            c.close();

            if (filled) {
                c.fillAndStroke();
            } else {
                c.stroke();
            }
        };
    });

    function createOpenAsyncArrow(widthFactor) {
        widthFactor = (widthFactor != null) ? widthFactor : 2;

        return function (c, shape, type, pe, unitX, unitY, size, source, sw, filled) {
            unitX = unitX * (size + sw);
            unitY = unitY * (size + sw);

            var pt = pe.clone();

            return function () {
                c.begin();
                c.moveTo(pt.x, pt.y);

                if (source) {
                    c.lineTo(pt.x - unitX - unitY / widthFactor, pt.y - unitY + unitX / widthFactor);
                } else {
                    c.lineTo(pt.x + unitY / widthFactor - unitX, pt.y - unitY - unitX / widthFactor);
                }

                c.stroke();
            };
        }
    };

    mxMarker.addMarker('openAsync', createOpenAsyncArrow(2));

    function arrow(canvas, shape, type, pe, unitX, unitY, size, source, sw, filled) {
        // The angle of the forward facing arrow sides against the x axis is
        // 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for
        // only half the strokewidth is processed ).
        var endOffsetX = unitX * sw * 1.118;
        var endOffsetY = unitY * sw * 1.118;

        unitX = unitX * (size + sw);
        unitY = unitY * (size + sw);

        var pt = pe.clone();
        pt.x -= endOffsetX;
        pt.y -= endOffsetY;

        var f = (type != mxConstants.ARROW_CLASSIC && type != mxConstants.ARROW_CLASSIC_THIN) ? 1 : 3 / 4;
        pe.x += -unitX * f - endOffsetX;
        pe.y += -unitY * f - endOffsetY;

        return function () {
            canvas.begin();
            canvas.moveTo(pt.x, pt.y);
            canvas.lineTo(pt.x - unitX - unitY / widthFactor, pt.y - unitY + unitX / widthFactor);

            if (type == mxConstants.ARROW_CLASSIC || type == mxConstants.ARROW_CLASSIC_THIN) {
                canvas.lineTo(pt.x - unitX * 3 / 4, pt.y - unitY * 3 / 4);
            }

            canvas.lineTo(pt.x + unitY / widthFactor - unitX, pt.y - unitY - unitX / widthFactor);
            canvas.close();

            if (filled) {
                canvas.fillAndStroke();
            } else {
                canvas.stroke();
            }
        };
    }

    // Handlers are only added if mxVertexHandler is defined (ie. not in embedded graph)
    if (typeof mxVertexHandler !== 'undefined') {
        function createHandle(state, keys, getPositionFn, setPositionFn, ignoreGrid, redrawEdges, executeFn) {
            var handle = new mxHandle(state, null, mxVertexHandler.prototype.secondaryHandleImage);

            handle.execute = function (me) {
                for (var i = 0; i < keys.length; i++) {
                    this.copyStyle(keys[i]);
                }

                if (executeFn) {
                    executeFn(me);
                }
            };

            handle.getPosition = getPositionFn;
            handle.setPosition = setPositionFn;
            handle.ignoreGrid = (ignoreGrid != null) ? ignoreGrid : true;

            // Overridden to update connected edges
            if (redrawEdges) {
                var positionChanged = handle.positionChanged;

                handle.positionChanged = function () {
                    positionChanged.apply(this, arguments);

                    // Redraws connected edges TODO: Include child edges
                    state.view.invalidate(this.state.cell);
                    state.view.validate();
                };
            }

            return handle;
        };

        function createArcHandle(state, yOffset) {
            return createHandle(state, [mxConstants.STYLE_ARCSIZE], function (bounds) {
                var tmp = (yOffset != null) ? yOffset : bounds.height / 8;

                if (mxUtils.getValue(state.style, mxConstants.STYLE_ABSOLUTE_ARCSIZE, 0) == '1') {
                    var arcSize = mxUtils.getValue(state.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;

                    return new mxPoint(bounds.x + bounds.width - Math.min(bounds.width / 2, arcSize), bounds.y + tmp);
                } else {
                    var arcSize = Math.max(0, parseFloat(mxUtils.getValue(state.style,
                        mxConstants.STYLE_ARCSIZE, mxConstants.RECTANGLE_ROUNDING_FACTOR * 100))) / 100;

                    return new mxPoint(bounds.x + bounds.width - Math.min(Math.max(bounds.width / 2, bounds.height / 2),
                        Math.min(bounds.width, bounds.height) * arcSize), bounds.y + tmp);
                }
            }, function (bounds, pt, me) {
                if (mxUtils.getValue(state.style, mxConstants.STYLE_ABSOLUTE_ARCSIZE, 0) == '1') {
                    this.state.style[mxConstants.STYLE_ARCSIZE] = Math.round(Math.max(0, Math.min(bounds.width,
                        (bounds.x + bounds.width - pt.x) * 2)));
                } else {
                    var f = Math.min(50, Math.max(0, (bounds.width - pt.x + bounds.x) * 100 /
                        Math.min(bounds.width, bounds.height)));
                    this.state.style[mxConstants.STYLE_ARCSIZE] = Math.round(f);
                }
            });
        }

        function createArcHandleFunction() {
            return function (state) {
                var handles = [];

                if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) {
                    handles.push(createArcHandle(state));
                }

                return handles;
            };
        };

        function createTrapezoidHandleFunction(max, defaultValue, fixedDefaultValue) {
            max = (max != null) ? max : 0.5;

            return function (state) {
                var handles = [createHandle(state, ['size'], function (bounds) {
                    var fixed = (fixedDefaultValue != null) ? mxUtils.getValue(this.state.style, 'fixedSize', '0') != '0' : null;
                    var size = Math.max(0, parseFloat(mxUtils.getValue(this.state.style, 'size', (fixed) ? fixedDefaultValue : defaultValue)));

                    return new mxPoint(bounds.x + Math.min(bounds.width * 0.75 * max, size * ((fixed) ? 0.75 : bounds.width * 0.75)), bounds.y + bounds.height / 4);
                }, function (bounds, pt) {
                    var fixed = (fixedDefaultValue != null) ? mxUtils.getValue(this.state.style, 'fixedSize', '0') != '0' : null;
                    var size = (fixed) ? (pt.x - bounds.x) : Math.max(0, Math.min(max, (pt.x - bounds.x) / bounds.width * 0.75));

                    this.state.style['size'] = size;
                }, false, true)];

                if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) {
                    handles.push(createArcHandle(state));
                }

                return handles;
            };
        };

        function createDisplayHandleFunction(defaultValue, allowArcHandle, max, redrawEdges, fixedDefaultValue) {
            max = (max != null) ? max : 0.5;

            return function (state) {
                var handles = [createHandle(state, ['size'], function (bounds) {
                    var fixed = (fixedDefaultValue != null) ? mxUtils.getValue(this.state.style, 'fixedSize', '0') != '0' : null;
                    var size = parseFloat(mxUtils.getValue(this.state.style, 'size', (fixed) ? fixedDefaultValue : defaultValue));

                    return new mxPoint(bounds.x + Math.max(0, Math.min(bounds.width * 0.5, size * ((fixed) ? 1 : bounds.width))), bounds.getCenterY());
                }, function (bounds, pt, me) {
                    var fixed = (fixedDefaultValue != null) ? mxUtils.getValue(this.state.style, 'fixedSize', '0') != '0' : null;
                    var size = (fixed) ? (pt.x - bounds.x) : Math.max(0, Math.min(max, (pt.x - bounds.x) / bounds.width));

                    this.state.style['size'] = size;
                }, false, redrawEdges)];

                if (allowArcHandle && mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) {
                    handles.push(createArcHandle(state));
                }

                return handles;
            };
        };

        function createCubeHandleFunction(factor, defaultValue, allowArcHandle) {
            return function (state) {
                var handles = [createHandle(state, ['size'], function (bounds) {
                    var size = Math.max(0, Math.min(bounds.width, Math.min(bounds.height, parseFloat(
                        mxUtils.getValue(this.state.style, 'size', defaultValue))))) * factor;

                    return new mxPoint(bounds.x + size, bounds.y + size);
                }, function (bounds, pt) {
                    this.state.style['size'] = Math.round(Math.max(0, Math.min(Math.min(bounds.width, pt.x - bounds.x),
                        Math.min(bounds.height, pt.y - bounds.y))) / factor);
                }, false)];

                if (allowArcHandle && mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) {
                    handles.push(createArcHandle(state));
                }

                return handles;
            };
        };

        function createCylinderHandleFunction(defaultValue) {
            return function (state) {
                return [createHandle(state, ['size'], function (bounds) {
                    var size = Math.max(0, Math.min(bounds.height * 0.5, parseFloat(mxUtils.getValue(this.state.style, 'size', defaultValue))));

                    return new mxPoint(bounds.x, bounds.y + size);
                }, function (bounds, pt) {
                    this.state.style['size'] = Math.max(0, pt.y - bounds.y);
                }, true)];
            }
        };

        function createArrowHandleFunction(maxSize) {
            return function (state) {
                return [createHandle(state, ['arrowWidth', 'arrowSize'], function (bounds) {
                    var aw = Math.max(0, Math.min(1, mxUtils.getValue(this.state.style, 'arrowWidth', SingleArrowShape.prototype.arrowWidth)));
                    var as = Math.max(0, Math.min(maxSize, mxUtils.getValue(this.state.style, 'arrowSize', SingleArrowShape.prototype.arrowSize)));

                    return new mxPoint(bounds.x + (1 - as) * bounds.width, bounds.y + (1 - aw) * bounds.height / 2);
                }, function (bounds, pt) {
                    this.state.style['arrowWidth'] = Math.max(0, Math.min(1, Math.abs(bounds.y + bounds.height / 2 - pt.y) / bounds.height * 2));
                    this.state.style['arrowSize'] = Math.max(0, Math.min(maxSize, (bounds.x + bounds.width - pt.x) / (bounds.width)));
                })];
            };
        };

        function createEdgeHandle(state, keys, start, getPosition, setPosition) {
            return createHandle(state, keys, function (bounds) {
                var pts = state.absolutePoints;
                var n = pts.length - 1;

                var tr = state.view.translate;
                var s = state.view.scale;

                var p0 = (start) ? pts[0] : pts[n];
                var p1 = (start) ? pts[1] : pts[n - 1];
                var dx = (start) ? p1.x - p0.x : p1.x - p0.x;
                var dy = (start) ? p1.y - p0.y : p1.y - p0.y;

                var dist = Math.sqrt(dx * dx + dy * dy);

                var pt = getPosition.call(this, dist, dx / dist, dy / dist, p0, p1);

                return new mxPoint(pt.x / s - tr.x, pt.y / s - tr.y);
            }, function (bounds, pt, me) {
                var pts = state.absolutePoints;
                var n = pts.length - 1;

                var tr = state.view.translate;
                var s = state.view.scale;

                var p0 = (start) ? pts[0] : pts[n];
                var p1 = (start) ? pts[1] : pts[n - 1];
                var dx = (start) ? p1.x - p0.x : p1.x - p0.x;
                var dy = (start) ? p1.y - p0.y : p1.y - p0.y;

                var dist = Math.sqrt(dx * dx + dy * dy);
                pt.x = (pt.x + tr.x) * s;
                pt.y = (pt.y + tr.y) * s;

                setPosition.call(this, dist, dx / dist, dy / dist, p0, p1, pt, me);
            });
        };

        function createEdgeWidthHandle(state, start, spacing) {
            return createEdgeHandle(state, ['width'], start, function (dist, nx, ny, p0, p1) {
                var w = state.shape.getEdgeWidth() * state.view.scale + spacing;

                return new mxPoint(p0.x + nx * dist / 4 + ny * w / 2, p0.y + ny * dist / 4 - nx * w / 2);
            }, function (dist, nx, ny, p0, p1, pt) {
                var w = Math.sqrt(mxUtils.ptSegDistSq(p0.x, p0.y, p1.x, p1.y, pt.x, pt.y));
                state.style['width'] = Math.round(w * 2) / state.view.scale - spacing;
            });
        };

        function ptLineDistance(x1, y1, x2, y2, x0, y0) {
            return Math.abs((y2 - y1) * x0 - (x2 - x1) * y0 + x2 * y1 - y2 * x1) / Math.sqrt((y2 - y1) * (y2 - y1) + (x2 - x1) * (x2 - x1));
        }

        var handleFactory = {
            'link': function (state) {
                var spacing = 10;

                return [createEdgeWidthHandle(state, true, spacing), createEdgeWidthHandle(state, false, spacing)];
            },
            'flexArrow': function (state) {
                // Do not use state.shape.startSize/endSize since it is cached
                var tol = state.view.graph.gridSize / state.view.scale;
                var handles = [];

                if (mxUtils.getValue(state.style, mxConstants.STYLE_STARTARROW, mxConstants.NONE) != mxConstants.NONE) {
                    handles.push(createEdgeHandle(state, ['width', mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE], true, function (dist, nx, ny, p0, p1) {
                        var w = (state.shape.getEdgeWidth() - state.shape.strokewidth) * state.view.scale;
                        var l = mxUtils.getNumber(state.style, mxConstants.STYLE_STARTSIZE, mxConstants.ARROW_SIZE / 5) * 3 * state.view.scale;

                        return new mxPoint(p0.x + nx * (l + state.shape.strokewidth * state.view.scale) + ny * w / 2,
                            p0.y + ny * (l + state.shape.strokewidth * state.view.scale) - nx * w / 2);
                    }, function (dist, nx, ny, p0, p1, pt, me) {
                        var w = Math.sqrt(mxUtils.ptSegDistSq(p0.x, p0.y, p1.x, p1.y, pt.x, pt.y));
                        var l = mxUtils.ptLineDist(p0.x, p0.y, p0.x + ny, p0.y - nx, pt.x, pt.y);

                        state.style[mxConstants.STYLE_STARTSIZE] = Math.round((l - state.shape.strokewidth) * 100 / 3) / 100 / state.view.scale;
                        state.style['width'] = Math.round(w * 2) / state.view.scale;

                        // Applies to opposite side
                        if (mxEvent.isControlDown(me.getEvent())) {
                            state.style[mxConstants.STYLE_ENDSIZE] = state.style[mxConstants.STYLE_STARTSIZE];
                        }

                        // Snaps to end geometry
                        if (!mxEvent.isAltDown(me.getEvent())) {
                            if (Math.abs(parseFloat(state.style[mxConstants.STYLE_STARTSIZE]) - parseFloat(state.style[mxConstants.STYLE_ENDSIZE])) < tol / 6) {
                                state.style[mxConstants.STYLE_STARTSIZE] = state.style[mxConstants.STYLE_ENDSIZE];
                            }
                        }
                    }));

                    handles.push(createEdgeHandle(state, ['startWidth', 'endWidth', mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE], true, function (dist, nx, ny, p0, p1) {
                        var w = (state.shape.getStartArrowWidth() - state.shape.strokewidth) * state.view.scale;
                        var l = mxUtils.getNumber(state.style, mxConstants.STYLE_STARTSIZE, mxConstants.ARROW_SIZE / 5) * 3 * state.view.scale;

                        return new mxPoint(p0.x + nx * (l + state.shape.strokewidth * state.view.scale) + ny * w / 2,
                            p0.y + ny * (l + state.shape.strokewidth * state.view.scale) - nx * w / 2);
                    }, function (dist, nx, ny, p0, p1, pt, me) {
                        var w = Math.sqrt(mxUtils.ptSegDistSq(p0.x, p0.y, p1.x, p1.y, pt.x, pt.y));
                        var l = mxUtils.ptLineDist(p0.x, p0.y, p0.x + ny, p0.y - nx, pt.x, pt.y);

                        state.style[mxConstants.STYLE_STARTSIZE] = Math.round((l - state.shape.strokewidth) * 100 / 3) / 100 / state.view.scale;
                        state.style['startWidth'] = Math.max(0, Math.round(w * 2) - state.shape.getEdgeWidth()) / state.view.scale;

                        // Applies to opposite side
                        if (mxEvent.isControlDown(me.getEvent())) {
                            state.style[mxConstants.STYLE_ENDSIZE] = state.style[mxConstants.STYLE_STARTSIZE];
                            state.style['endWidth'] = state.style['startWidth'];
                        }

                        // Snaps to endWidth
                        if (!mxEvent.isAltDown(me.getEvent())) {
                            if (Math.abs(parseFloat(state.style[mxConstants.STYLE_STARTSIZE]) - parseFloat(state.style[mxConstants.STYLE_ENDSIZE])) < tol / 6) {
                                state.style[mxConstants.STYLE_STARTSIZE] = state.style[mxConstants.STYLE_ENDSIZE];
                            }

                            if (Math.abs(parseFloat(state.style['startWidth']) - parseFloat(state.style['endWidth'])) < tol) {
                                state.style['startWidth'] = state.style['endWidth'];
                            }
                        }
                    }));
                }

                if (mxUtils.getValue(state.style, mxConstants.STYLE_ENDARROW, mxConstants.NONE) != mxConstants.NONE) {
                    handles.push(createEdgeHandle(state, ['width', mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE], false, function (dist, nx, ny, p0, p1) {
                        var w = (state.shape.getEdgeWidth() - state.shape.strokewidth) * state.view.scale;
                        var l = mxUtils.getNumber(state.style, mxConstants.STYLE_ENDSIZE, mxConstants.ARROW_SIZE / 5) * 3 * state.view.scale;

                        return new mxPoint(p0.x + nx * (l + state.shape.strokewidth * state.view.scale) - ny * w / 2,
                            p0.y + ny * (l + state.shape.strokewidth * state.view.scale) + nx * w / 2);
                    }, function (dist, nx, ny, p0, p1, pt, me) {
                        var w = Math.sqrt(mxUtils.ptSegDistSq(p0.x, p0.y, p1.x, p1.y, pt.x, pt.y));
                        var l = mxUtils.ptLineDist(p0.x, p0.y, p0.x + ny, p0.y - nx, pt.x, pt.y);

                        state.style[mxConstants.STYLE_ENDSIZE] = Math.round((l - state.shape.strokewidth) * 100 / 3) / 100 / state.view.scale;
                        state.style['width'] = Math.round(w * 2) / state.view.scale;

                        // Applies to opposite side
                        if (mxEvent.isControlDown(me.getEvent())) {
                            state.style[mxConstants.STYLE_STARTSIZE] = state.style[mxConstants.STYLE_ENDSIZE];
                        }

                        // Snaps to start geometry
                        if (!mxEvent.isAltDown(me.getEvent())) {
                            if (Math.abs(parseFloat(state.style[mxConstants.STYLE_ENDSIZE]) - parseFloat(state.style[mxConstants.STYLE_STARTSIZE])) < tol / 6) {
                                state.style[mxConstants.STYLE_ENDSIZE] = state.style[mxConstants.STYLE_STARTSIZE];
                            }
                        }
                    }));

                    handles.push(createEdgeHandle(state, ['startWidth', 'endWidth', mxConstants.STYLE_STARTSIZE, mxConstants.STYLE_ENDSIZE], false, function (dist, nx, ny, p0, p1) {
                        var w = (state.shape.getEndArrowWidth() - state.shape.strokewidth) * state.view.scale;
                        var l = mxUtils.getNumber(state.style, mxConstants.STYLE_ENDSIZE, mxConstants.ARROW_SIZE / 5) * 3 * state.view.scale;

                        return new mxPoint(p0.x + nx * (l + state.shape.strokewidth * state.view.scale) - ny * w / 2,
                            p0.y + ny * (l + state.shape.strokewidth * state.view.scale) + nx * w / 2);
                    }, function (dist, nx, ny, p0, p1, pt, me) {
                        var w = Math.sqrt(mxUtils.ptSegDistSq(p0.x, p0.y, p1.x, p1.y, pt.x, pt.y));
                        var l = mxUtils.ptLineDist(p0.x, p0.y, p0.x + ny, p0.y - nx, pt.x, pt.y);

                        state.style[mxConstants.STYLE_ENDSIZE] = Math.round((l - state.shape.strokewidth) * 100 / 3) / 100 / state.view.scale;
                        state.style['endWidth'] = Math.max(0, Math.round(w * 2) - state.shape.getEdgeWidth()) / state.view.scale;

                        // Applies to opposite side
                        if (mxEvent.isControlDown(me.getEvent())) {
                            state.style[mxConstants.STYLE_STARTSIZE] = state.style[mxConstants.STYLE_ENDSIZE];
                            state.style['startWidth'] = state.style['endWidth'];
                        }

                        // Snaps to start geometry
                        if (!mxEvent.isAltDown(me.getEvent())) {
                            if (Math.abs(parseFloat(state.style[mxConstants.STYLE_ENDSIZE]) - parseFloat(state.style[mxConstants.STYLE_STARTSIZE])) < tol / 6) {
                                state.style[mxConstants.STYLE_ENDSIZE] = state.style[mxConstants.STYLE_STARTSIZE];
                            }

                            if (Math.abs(parseFloat(state.style['endWidth']) - parseFloat(state.style['startWidth'])) < tol) {
                                state.style['endWidth'] = state.style['startWidth'];
                            }
                        }
                    }));
                }

                return handles;
            },
            'swimlane': function (state) {
                var handles = [];

                if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED)) {
                    var size = parseFloat(mxUtils.getValue(state.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE));
                    handles.push(createArcHandle(state, size / 2));
                }

                // Start size handle must be last item in handles for hover to work in tables (see mouse event handler in Graph)
                handles.push(createHandle(state, [mxConstants.STYLE_STARTSIZE], function (bounds) {
                    var size = parseFloat(mxUtils.getValue(state.style, mxConstants.STYLE_STARTSIZE, mxConstants.DEFAULT_STARTSIZE));

                    if (mxUtils.getValue(state.style, mxConstants.STYLE_HORIZONTAL, 1) == 1) {
                        return new mxPoint(bounds.getCenterX(), bounds.y + Math.max(0, Math.min(bounds.height, size)));
                    } else {
                        return new mxPoint(bounds.x + Math.max(0, Math.min(bounds.width, size)), bounds.getCenterY());
                    }
                }, function (bounds, pt) {
                    state.style[mxConstants.STYLE_STARTSIZE] =
                        (mxUtils.getValue(this.state.style, mxConstants.STYLE_HORIZONTAL, 1) == 1) ?
                            Math.round(Math.max(0, Math.min(bounds.height, pt.y - bounds.y))) :
                            Math.round(Math.max(0, Math.min(bounds.width, pt.x - bounds.x)));
                }, false, null, function (me) {
                    if (mxEvent.isControlDown(me.getEvent())) {
                        var graph = state.view.graph;

                        if (graph.isTableRow(state.cell) || graph.isTableCell(state.cell)) {
                            var dir = graph.getSwimlaneDirection(state.style);
                            var parent = graph.model.getParent(state.cell);
                            var cells = graph.model.getChildCells(parent, true);
                            var temp = [];

                            for (var i = 0; i < cells.length; i++) {
                                // Finds siblings with the same direction and to set start size
                                if (cells[i] != state.cell && graph.isSwimlane(cells[i]) &&
                                    graph.getSwimlaneDirection(graph.getCurrentCellStyle(
                                        cells[i])) == dir) {
                                    temp.push(cells[i]);
                                }
                            }

                            graph.setCellStyles(mxConstants.STYLE_STARTSIZE,
                                state.style[mxConstants.STYLE_STARTSIZE], temp);
                        }
                    }
                }));

                return handles;
            },
            'label': createArcHandleFunction(),
            'ext': createArcHandleFunction(),
            'rectangle': createArcHandleFunction(),
            'triangle': createArcHandleFunction(),
            'rhombus': createArcHandleFunction(),
            'umlLifeline': function (state) {
                return [createHandle(state, ['size'], function (bounds) {
                    var size = Math.max(0, Math.min(bounds.height, parseFloat(mxUtils.getValue(this.state.style, 'size', UmlLifeline.prototype.size))));

                    return new mxPoint(bounds.getCenterX(), bounds.y + size);
                }, function (bounds, pt) {
                    this.state.style['size'] = Math.round(Math.max(0, Math.min(bounds.height, pt.y - bounds.y)));
                }, false)];
            },
            'umlFrame': function (state) {
                var handles = [createHandle(state, ['width', 'height'], function (bounds) {
                    var w0 = Math.max(UmlFrame.prototype.corner, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'width', UmlFrame.prototype.width)));
                    var h0 = Math.max(UmlFrame.prototype.corner * 1.5, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'height', UmlFrame.prototype.height)));

                    return new mxPoint(bounds.x + w0, bounds.y + h0);
                }, function (bounds, pt) {
                    this.state.style['width'] = Math.round(Math.max(UmlFrame.prototype.corner, Math.min(bounds.width, pt.x - bounds.x)));
                    this.state.style['height'] = Math.round(Math.max(UmlFrame.prototype.corner * 1.5, Math.min(bounds.height, pt.y - bounds.y)));
                }, false)];

                return handles;
            },
            'process': function (state) {
                var handles = [createHandle(state, ['size'], function (bounds) {

                    var fixed = mxUtils.getValue(this.state.style, 'fixedSize', '0') != '0';
                    var size = parseFloat(mxUtils.getValue(this.state.style, 'size', ProcessShape.prototype.size));

                    return (fixed) ? new mxPoint(bounds.x + size, bounds.y + bounds.height / 4) : new mxPoint(bounds.x + bounds.width * size, bounds.y + bounds.height / 4);
                }, function (bounds, pt) {
                    var fixed = mxUtils.getValue(this.state.style, 'fixedSize', '0') != '0';
                    var size = (fixed) ? Math.max(0, Math.min(bounds.width * 0.5, (pt.x - bounds.x))) : Math.max(0, Math.min(0.5, (pt.x - bounds.x) / bounds.width));
                    this.state.style['size'] = size;
                }, false)];

                if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) {
                    handles.push(createArcHandle(state));
                }

                return handles;
            },
            'cross': function (state) {
                return [createHandle(state, ['size'], function (bounds) {
                    var m = Math.min(bounds.width, bounds.height);
                    var size = Math.max(0, Math.min(1, mxUtils.getValue(this.state.style, 'size', CrossShape.prototype.size))) * m / 2;

                    return new mxPoint(bounds.getCenterX() - size, bounds.getCenterY() - size);
                }, function (bounds, pt) {
                    var m = Math.min(bounds.width, bounds.height);
                    this.state.style['size'] = Math.max(0, Math.min(1, Math.min((Math.max(0, bounds.getCenterY() - pt.y) / m) * 2,
                        (Math.max(0, bounds.getCenterX() - pt.x) / m) * 2)));
                })];
            },
            'note': function (state) {
                return [createHandle(state, ['size'], function (bounds) {
                    var size = Math.max(0, Math.min(bounds.width, Math.min(bounds.height, parseFloat(
                        mxUtils.getValue(this.state.style, 'size', NoteShape.prototype.size)))));

                    return new mxPoint(bounds.x + bounds.width - size, bounds.y + size);
                }, function (bounds, pt) {
                    this.state.style['size'] = Math.round(Math.max(0, Math.min(Math.min(bounds.width, bounds.x + bounds.width - pt.x),
                        Math.min(bounds.height, pt.y - bounds.y))));
                })];
            },
            'note2': function (state) {
                return [createHandle(state, ['size'], function (bounds) {
                    var size = Math.max(0, Math.min(bounds.width, Math.min(bounds.height, parseFloat(
                        mxUtils.getValue(this.state.style, 'size', NoteShape2.prototype.size)))));

                    return new mxPoint(bounds.x + bounds.width - size, bounds.y + size);
                }, function (bounds, pt) {
                    this.state.style['size'] = Math.round(Math.max(0, Math.min(Math.min(bounds.width, bounds.x + bounds.width - pt.x),
                        Math.min(bounds.height, pt.y - bounds.y))));
                })];
            },
            'manualInput': function (state) {
                var handles = [createHandle(state, ['size'], function (bounds) {
                    var size = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'size', ManualInputShape.prototype.size)));

                    return new mxPoint(bounds.x + bounds.width / 4, bounds.y + size * 3 / 4);
                }, function (bounds, pt) {
                    this.state.style['size'] = Math.round(Math.max(0, Math.min(bounds.height, (pt.y - bounds.y) * 4 / 3)));
                }, false)];

                if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) {
                    handles.push(createArcHandle(state));
                }

                return handles;
            },
            'dataStorage': function (state) {
                return [createHandle(state, ['size'], function (bounds) {
                    var fixed = mxUtils.getValue(this.state.style, 'fixedSize', '0') != '0';
                    var size = parseFloat(mxUtils.getValue(this.state.style, 'size', (fixed) ? DataStorageShape.prototype.fixedSize : DataStorageShape.prototype.size));

                    return new mxPoint(bounds.x + bounds.width - size * ((fixed) ? 1 : bounds.width), bounds.getCenterY());
                }, function (bounds, pt) {
                    var fixed = mxUtils.getValue(this.state.style, 'fixedSize', '0') != '0';
                    var size = (fixed) ? Math.max(0, Math.min(bounds.width, (bounds.x + bounds.width - pt.x))) : Math.max(0, Math.min(1, (bounds.x + bounds.width - pt.x) / bounds.width));

                    this.state.style['size'] = size;
                }, false)];
            },
            'callout': function (state) {
                var handles = [createHandle(state, ['size', 'position'], function (bounds) {
                    var size = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'size', CalloutShape.prototype.size)));
                    var position = Math.max(0, Math.min(1, mxUtils.getValue(this.state.style, 'position', CalloutShape.prototype.position)));
                    var base = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'base', CalloutShape.prototype.base)));

                    return new mxPoint(bounds.x + position * bounds.width, bounds.y + bounds.height - size);
                }, function (bounds, pt) {
                    var base = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'base', CalloutShape.prototype.base)));
                    this.state.style['size'] = Math.round(Math.max(0, Math.min(bounds.height, bounds.y + bounds.height - pt.y)));
                    this.state.style['position'] = Math.round(Math.max(0, Math.min(1, (pt.x - bounds.x) / bounds.width)) * 100) / 100;
                }, false), createHandle(state, ['position2'], function (bounds) {
                    var position2 = Math.max(0, Math.min(1, mxUtils.getValue(this.state.style, 'position2', CalloutShape.prototype.position2)));

                    return new mxPoint(bounds.x + position2 * bounds.width, bounds.y + bounds.height);
                }, function (bounds, pt) {
                    this.state.style['position2'] = Math.round(Math.max(0, Math.min(1, (pt.x - bounds.x) / bounds.width)) * 100) / 100;
                }, false), createHandle(state, ['base'], function (bounds) {
                    var size = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'size', CalloutShape.prototype.size)));
                    var position = Math.max(0, Math.min(1, mxUtils.getValue(this.state.style, 'position', CalloutShape.prototype.position)));
                    var base = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'base', CalloutShape.prototype.base)));

                    return new mxPoint(bounds.x + Math.min(bounds.width, position * bounds.width + base), bounds.y + bounds.height - size);
                }, function (bounds, pt) {
                    var position = Math.max(0, Math.min(1, mxUtils.getValue(this.state.style, 'position', CalloutShape.prototype.position)));

                    this.state.style['base'] = Math.round(Math.max(0, Math.min(bounds.width, pt.x - bounds.x - position * bounds.width)));
                }, false)];

                if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) {
                    handles.push(createArcHandle(state));
                }

                return handles;
            },
            'internalStorage': function (state) {
                var handles = [createHandle(state, ['dx', 'dy'], function (bounds) {
                    var dx = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'dx', InternalStorageShape.prototype.dx)));
                    var dy = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'dy', InternalStorageShape.prototype.dy)));

                    return new mxPoint(bounds.x + dx, bounds.y + dy);
                }, function (bounds, pt) {
                    this.state.style['dx'] = Math.round(Math.max(0, Math.min(bounds.width, pt.x - bounds.x)));
                    this.state.style['dy'] = Math.round(Math.max(0, Math.min(bounds.height, pt.y - bounds.y)));
                }, false)];

                if (mxUtils.getValue(state.style, mxConstants.STYLE_ROUNDED, false)) {
                    handles.push(createArcHandle(state));
                }

                return handles;
            },
            'module': function (state) {
                var handles = [createHandle(state, ['jettyWidth', 'jettyHeight'], function (bounds) {
                    var dx = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'jettyWidth', ModuleShape.prototype.jettyWidth)));
                    var dy = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'jettyHeight', ModuleShape.prototype.jettyHeight)));

                    return new mxPoint(bounds.x + dx / 2, bounds.y + dy * 2);
                }, function (bounds, pt) {
                    this.state.style['jettyWidth'] = Math.round(Math.max(0, Math.min(bounds.width, pt.x - bounds.x)) * 2);
                    this.state.style['jettyHeight'] = Math.round(Math.max(0, Math.min(bounds.height, pt.y - bounds.y)) / 2);
                })];

                return handles;
            },
            'corner': function (state) {
                return [createHandle(state, ['dx', 'dy'], function (bounds) {
                    var dx = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'dx', CornerShape.prototype.dx)));
                    var dy = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'dy', CornerShape.prototype.dy)));

                    return new mxPoint(bounds.x + dx, bounds.y + dy);
                }, function (bounds, pt) {
                    this.state.style['dx'] = Math.round(Math.max(0, Math.min(bounds.width, pt.x - bounds.x)));
                    this.state.style['dy'] = Math.round(Math.max(0, Math.min(bounds.height, pt.y - bounds.y)));
                }, false)];
            },
            'tee': function (state) {
                return [createHandle(state, ['dx', 'dy'], function (bounds) {
                    var dx = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'dx', TeeShape.prototype.dx)));
                    var dy = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'dy', TeeShape.prototype.dy)));

                    return new mxPoint(bounds.x + (bounds.width + dx) / 2, bounds.y + dy);
                }, function (bounds, pt) {
                    this.state.style['dx'] = Math.round(Math.max(0, Math.min(bounds.width / 2, (pt.x - bounds.x - bounds.width / 2)) * 2));
                    this.state.style['dy'] = Math.round(Math.max(0, Math.min(bounds.height, pt.y - bounds.y)));
                }, false)];
            },
            'singleArrow': createArrowHandleFunction(1),
            'doubleArrow': createArrowHandleFunction(0.5),
            'folder': function (state) {
                return [createHandle(state, ['tabWidth', 'tabHeight'], function (bounds) {
                    var tw = Math.max(0, Math.min(bounds.width, mxUtils.getValue(this.state.style, 'tabWidth', FolderShape.prototype.tabWidth)));
                    var th = Math.max(0, Math.min(bounds.height, mxUtils.getValue(this.state.style, 'tabHeight', FolderShape.prototype.tabHeight)));

                    if (mxUtils.getValue(this.state.style, 'tabPosition', FolderShape.prototype.tabPosition) == mxConstants.ALIGN_RIGHT) {
                        tw = bounds.width - tw;
                    }

                    return new mxPoint(bounds.x + tw, bounds.y + th);
                }, function (bounds, pt) {
                    var tw = Math.max(0, Math.min(bounds.width, pt.x - bounds.x));

                    if (mxUtils.getValue(this.state.style, 'tabPosition', FolderShape.prototype.tabPosition) == mxConstants.ALIGN_RIGHT) {
                        tw = bounds.width - tw;
                    }

                    this.state.style['tabWidth'] = Math.round(tw);
                    this.state.style['tabHeight'] = Math.round(Math.max(0, Math.min(bounds.height, pt.y - bounds.y)));
                }, false)];
            },
            'document': function (state) {
                return [createHandle(state, ['size'], function (bounds) {
                    var size = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'size', DocumentShape.prototype.size))));

                    return new mxPoint(bounds.x + 3 * bounds.width / 4, bounds.y + (1 - size) * bounds.height);
                }, function (bounds, pt) {
                    this.state.style['size'] = Math.max(0, Math.min(1, (bounds.y + bounds.height - pt.y) / bounds.height));
                }, false)];
            },
            'tape': function (state) {
                return [createHandle(state, ['size'], function (bounds) {
                    var size = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'size', TapeShape.prototype.size))));

                    return new mxPoint(bounds.getCenterX(), bounds.y + size * bounds.height / 2);
                }, function (bounds, pt) {
                    this.state.style['size'] = Math.max(0, Math.min(1, ((pt.y - bounds.y) / bounds.height) * 2));
                }, false)];
            },
            'isoCube2': function (state) {
                return [createHandle(state, ['isoAngle'], function (bounds) {
                    var isoAngle = Math.max(0.01, Math.min(94, parseFloat(mxUtils.getValue(this.state.style, 'isoAngle', IsoCubeShape2.isoAngle)))) * Math.PI / 200;
                    var isoH = Math.min(bounds.width * Math.tan(isoAngle), bounds.height * 0.5);

                    return new mxPoint(bounds.x, bounds.y + isoH);
                }, function (bounds, pt) {
                    this.state.style['isoAngle'] = Math.max(0, (pt.y - bounds.y) * 50 / bounds.height);
                }, true)];
            },
            'cylinder2': createCylinderHandleFunction(CylinderShape.prototype.size),
            'cylinder3': createCylinderHandleFunction(CylinderShape3.prototype.size),
            'offPageConnector': function (state) {
                return [createHandle(state, ['size'], function (bounds) {
                    var size = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'size', OffPageConnectorShape.prototype.size))));

                    return new mxPoint(bounds.getCenterX(), bounds.y + (1 - size) * bounds.height);
                }, function (bounds, pt) {
                    this.state.style['size'] = Math.max(0, Math.min(1, (bounds.y + bounds.height - pt.y) / bounds.height));
                }, false)];
            },
            'step': createDisplayHandleFunction(StepShape.prototype.size, true, null, true, StepShape.prototype.fixedSize),
            'hexagon': createDisplayHandleFunction(HexagonShape.prototype.size, true, 0.5, true, HexagonShape.prototype.fixedSize),
            'curlyBracket': createDisplayHandleFunction(CurlyBracketShape.prototype.size, false),
            'display': createDisplayHandleFunction(DisplayShape.prototype.size, false),
            'cube': createCubeHandleFunction(1, CubeShape.prototype.size, false),
            'card': createCubeHandleFunction(0.5, CardShape.prototype.size, true),
            'loopLimit': createCubeHandleFunction(0.5, LoopLimitShape.prototype.size, true),
            'trapezoid': createTrapezoidHandleFunction(0.5, TrapezoidShape.prototype.size, TrapezoidShape.prototype.fixedSize),
            'parallelogram': createTrapezoidHandleFunction(1, ParallelogramShape.prototype.size, ParallelogramShape.prototype.fixedSize)
        };

        // Exposes custom handles
        Graph.createHandle = createHandle;
        Graph.handleFactory = handleFactory;

        var vertexHandlerCreateCustomHandles = mxVertexHandler.prototype.createCustomHandles;

        mxVertexHandler.prototype.createCustomHandles = function () {
            var handles = vertexHandlerCreateCustomHandles.apply(this, arguments);

            if (this.graph.isCellRotatable(this.state.cell))
                // LATER: Make locked state independent of rotatable flag, fix toggle if default is false
                //if (this.graph.isCellResizable(this.state.cell) || this.graph.isCellMovable(this.state.cell))
            {
                var name = this.state.style['shape'];

                if (mxCellRenderer.defaultShapes[name] == null &&
                    mxStencilRegistry.getStencil(name) == null) {
                    name = mxConstants.SHAPE_RECTANGLE;
                } else if (this.state.view.graph.isSwimlane(this.state.cell)) {
                    name = mxConstants.SHAPE_SWIMLANE;
                }

                var fn = handleFactory[name];

                if (fn == null && this.state.shape != null && this.state.shape.isRoundable()) {
                    fn = handleFactory[mxConstants.SHAPE_RECTANGLE];
                }

                if (fn != null) {
                    var temp = fn(this.state);

                    if (temp != null) {
                        if (handles == null) {
                            handles = temp;
                        } else {
                            handles = handles.concat(temp);
                        }
                    }
                }
            }

            return handles;
        };

        mxEdgeHandler.prototype.createCustomHandles = function () {
            var name = this.state.style['shape'];

            if (mxCellRenderer.defaultShapes[name] == null &&
                mxStencilRegistry.getStencil(name) == null) {
                name = mxConstants.SHAPE_CONNECTOR;
            }

            var fn = handleFactory[name];

            if (fn != null) {
                return fn(this.state);
            }

            return null;
        }
    } else {
        // Dummy entries to avoid NPE in embed mode
        Graph.createHandle = function () {
        };
        Graph.handleFactory = {};
    }

    var isoHVector = new mxPoint(1, 0);
    var isoVVector = new mxPoint(1, 0);

    var alpha1 = mxUtils.toRadians(-30);

    var cos1 = Math.cos(alpha1);
    var sin1 = Math.sin(alpha1);

    isoHVector = mxUtils.getRotatedPoint(isoHVector, cos1, sin1);

    var alpha2 = mxUtils.toRadians(-150);

    var cos2 = Math.cos(alpha2);
    var sin2 = Math.sin(alpha2);

    isoVVector = mxUtils.getRotatedPoint(isoVVector, cos2, sin2);

    mxEdgeStyle.IsometricConnector = function (state, source, target, points, result) {
        var view = state.view;
        var pt = (points != null && points.length > 0) ? points[0] : null;
        var pts = state.absolutePoints;
        var p0 = pts[0];
        var pe = pts[pts.length - 1];

        if (pt != null) {
            pt = view.transformControlPoint(state, pt);
        }

        if (p0 == null) {
            if (source != null) {
                p0 = new mxPoint(source.getCenterX(), source.getCenterY());
            }
        }

        if (pe == null) {
            if (target != null) {
                pe = new mxPoint(target.getCenterX(), target.getCenterY());
            }
        }

        var a1 = isoHVector.x;
        var a2 = isoHVector.y;

        var b1 = isoVVector.x;
        var b2 = isoVVector.y;

        var elbow = mxUtils.getValue(state.style, 'elbow', 'horizontal') == 'horizontal';

        if (pe != null && p0 != null) {
            var last = p0;

            function isoLineTo(x, y, ignoreFirst) {
                var c1 = x - last.x;
                var c2 = y - last.y;

                // Solves for isometric base vectors
                var h = (b2 * c1 - b1 * c2) / (a1 * b2 - a2 * b1);
                var v = (a2 * c1 - a1 * c2) / (a2 * b1 - a1 * b2);

                if (elbow) {
                    if (ignoreFirst) {
                        last = new mxPoint(last.x + a1 * h, last.y + a2 * h);
                        result.push(last);
                    }

                    last = new mxPoint(last.x + b1 * v, last.y + b2 * v);
                    result.push(last);
                } else {
                    if (ignoreFirst) {
                        last = new mxPoint(last.x + b1 * v, last.y + b2 * v);
                        result.push(last);
                    }

                    last = new mxPoint(last.x + a1 * h, last.y + a2 * h);
                    result.push(last);
                }
            };

            if (pt == null) {
                pt = new mxPoint(p0.x + (pe.x - p0.x) / 2, p0.y + (pe.y - p0.y) / 2);
            }

            isoLineTo(pt.x, pt.y, true);
            isoLineTo(pe.x, pe.y, false);
        }
    };

    mxStyleRegistry.putValue('isometricEdgeStyle', mxEdgeStyle.IsometricConnector);

    var graphCreateEdgeHandler = Graph.prototype.createEdgeHandler;
    Graph.prototype.createEdgeHandler = function (state, edgeStyle) {
        if (edgeStyle == mxEdgeStyle.IsometricConnector) {
            var handler = new mxElbowEdgeHandler(state);
            handler.snapToTerminals = false;

            return handler;
        }

        return graphCreateEdgeHandler.apply(this, arguments);
    };

    // Defines connection points for all shapes
    IsoRectangleShape.prototype.constraints = [];

    IsoCubeShape.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var tan30 = Math.tan(mxUtils.toRadians(30));
        var tan30Dx = (0.5 - tan30) / 2;
        var m = Math.min(w, h / (0.5 + tan30));
        var dx = (w - m) / 2;
        var dy = (h - m) / 2;

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, dy + 0.25 * m));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx + 0.5 * m, dy + m * tan30Dx));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx + m, dy + 0.25 * m));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx + m, dy + 0.75 * m));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx + 0.5 * m, dy + (1 - tan30Dx) * m));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, dy + 0.75 * m));

        return (constr);
    };

    IsoCubeShape2.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var isoAngle = Math.max(0.01, Math.min(94, parseFloat(mxUtils.getValue(this.style, 'isoAngle', this.isoAngle)))) * Math.PI / 200;
        var isoH = Math.min(w * Math.tan(isoAngle), h * 0.5);

        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, isoH));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, h - isoH));
        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 1), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h - isoH));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, isoH));

        return (constr);
    }

    CalloutShape.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var arcSize = mxUtils.getValue(this.style, mxConstants.STYLE_ARCSIZE, mxConstants.LINE_ARCSIZE) / 2;
        var s = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var dx = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'position', this.position))));
        var dx2 = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'position2', this.position2))));
        var base = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'base', this.base))));

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0.25, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0.75, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, (h - s) * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, h - s));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx2, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h - s));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, (h - s) * 0.5));

        if (w >= s * 2) {
            constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
        }

        return (constr);
    };

    mxRectangleShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0), true),
        new mxConnectionConstraint(new mxPoint(0.1, 0), true),
        new mxConnectionConstraint(new mxPoint(0.2, 0), true),
        new mxConnectionConstraint(new mxPoint(0.3, 0), true),
        new mxConnectionConstraint(new mxPoint(0.4, 0), true),
        new mxConnectionConstraint(new mxPoint(0.5, 0), true),
        new mxConnectionConstraint(new mxPoint(0.6, 0), true),
        new mxConnectionConstraint(new mxPoint(0.7, 0), true),
        new mxConnectionConstraint(new mxPoint(0.8, 0), true),
        new mxConnectionConstraint(new mxPoint(0.9, 0), true),
        new mxConnectionConstraint(new mxPoint(0.05, 0), true),
        new mxConnectionConstraint(new mxPoint(0.15, 0), true),
        new mxConnectionConstraint(new mxPoint(0.25, 0), true),
        new mxConnectionConstraint(new mxPoint(0.35, 0), true),
        new mxConnectionConstraint(new mxPoint(0.45, 0), true),
        new mxConnectionConstraint(new mxPoint(0.55, 0), true),
        new mxConnectionConstraint(new mxPoint(0.65, 0), true),
        new mxConnectionConstraint(new mxPoint(0.75, 0), true),
        new mxConnectionConstraint(new mxPoint(0.85, 0), true),
        new mxConnectionConstraint(new mxPoint(1, 0), true),
        new mxConnectionConstraint(new mxPoint(0, 0.1), true),
        new mxConnectionConstraint(new mxPoint(0, 0.2), true),
        new mxConnectionConstraint(new mxPoint(0, 0.3), true),
        new mxConnectionConstraint(new mxPoint(0, 0.4), true),
        new mxConnectionConstraint(new mxPoint(0, 0.5), true),
        new mxConnectionConstraint(new mxPoint(0, 0.6), true),
        new mxConnectionConstraint(new mxPoint(0, 0.7), true),
        new mxConnectionConstraint(new mxPoint(0, 0.8), true),
        new mxConnectionConstraint(new mxPoint(0, 0.9), true),
        new mxConnectionConstraint(new mxPoint(0, 0.05), true),
        new mxConnectionConstraint(new mxPoint(0, 0.15), true),
        new mxConnectionConstraint(new mxPoint(0, 0.25), true),
        new mxConnectionConstraint(new mxPoint(0, 0.35), true),
        new mxConnectionConstraint(new mxPoint(0, 0.45), true),
        new mxConnectionConstraint(new mxPoint(0, 0.55), true),
        new mxConnectionConstraint(new mxPoint(0, 0.65), true),
        new mxConnectionConstraint(new mxPoint(0, 0.75), true),
        new mxConnectionConstraint(new mxPoint(0, 0.85), true),
        new mxConnectionConstraint(new mxPoint(1, 0.1), true),
        new mxConnectionConstraint(new mxPoint(1, 0.2), true),
        new mxConnectionConstraint(new mxPoint(1, 0.3), true),
        new mxConnectionConstraint(new mxPoint(1, 0.4), true),
        new mxConnectionConstraint(new mxPoint(1, 0.5), true),
        new mxConnectionConstraint(new mxPoint(1, 0.6), true),
        new mxConnectionConstraint(new mxPoint(1, 0.7), true),
        new mxConnectionConstraint(new mxPoint(1, 0.8), true),
        new mxConnectionConstraint(new mxPoint(1, 0.9), true),
        new mxConnectionConstraint(new mxPoint(1, 0.05), true),
        new mxConnectionConstraint(new mxPoint(1, 0.15), true),
        new mxConnectionConstraint(new mxPoint(1, 0.25), true),
        new mxConnectionConstraint(new mxPoint(1, 0.35), true),
        new mxConnectionConstraint(new mxPoint(1, 0.45), true),
        new mxConnectionConstraint(new mxPoint(1, 0.55), true),
        new mxConnectionConstraint(new mxPoint(1, 0.65), true),
        new mxConnectionConstraint(new mxPoint(1, 0.75), true),
        new mxConnectionConstraint(new mxPoint(1, 0.85), true),
        new mxConnectionConstraint(new mxPoint(0, 1), true),
        new mxConnectionConstraint(new mxPoint(0.1, 1), true),
        new mxConnectionConstraint(new mxPoint(0.2, 1), true),
        new mxConnectionConstraint(new mxPoint(0.3, 1), true),
        new mxConnectionConstraint(new mxPoint(0.4, 1), true),
        new mxConnectionConstraint(new mxPoint(0.5, 1), true),
        new mxConnectionConstraint(new mxPoint(0.6, 1), true),
        new mxConnectionConstraint(new mxPoint(0.7, 1), true),
        new mxConnectionConstraint(new mxPoint(0.8, 1), true),
        new mxConnectionConstraint(new mxPoint(0.9, 1), true),
        new mxConnectionConstraint(new mxPoint(0.05, 1), true),
        new mxConnectionConstraint(new mxPoint(0.15, 1), true),
        new mxConnectionConstraint(new mxPoint(0.25, 1), true),
        new mxConnectionConstraint(new mxPoint(0.35, 1), true),
        new mxConnectionConstraint(new mxPoint(0.45, 1), true),
        new mxConnectionConstraint(new mxPoint(0.55, 1), true),
        new mxConnectionConstraint(new mxPoint(0.65, 1), true),
        new mxConnectionConstraint(new mxPoint(0.75, 1), true),
        new mxConnectionConstraint(new mxPoint(0.85, 1), true),
        new mxConnectionConstraint(new mxPoint(0.15, 0), true),
        new mxConnectionConstraint(new mxPoint(0.25, 0), true),
        new mxConnectionConstraint(new mxPoint(0.35, 0), true),
        new mxConnectionConstraint(new mxPoint(0.45, 0), true),
        new mxConnectionConstraint(new mxPoint(0.55, 0), true),
        new mxConnectionConstraint(new mxPoint(0.65, 0), true),
        new mxConnectionConstraint(new mxPoint(0.75, 0), true),
        new mxConnectionConstraint(new mxPoint(0.85, 0), true),
        new mxConnectionConstraint(new mxPoint(0.95, 0), true),
        new mxConnectionConstraint(new mxPoint(0.05, 0), true),
        new mxConnectionConstraint(new mxPoint(0.15, 0), true),
        new mxConnectionConstraint(new mxPoint(0.25, 0), true),
        new mxConnectionConstraint(new mxPoint(0.35, 0), true),
        new mxConnectionConstraint(new mxPoint(0.45, 0), true),
        new mxConnectionConstraint(new mxPoint(0.55, 0), true),
        new mxConnectionConstraint(new mxPoint(0.65, 0), true),
        new mxConnectionConstraint(new mxPoint(0.75, 0), true),
        new mxConnectionConstraint(new mxPoint(0.85, 0), true),
        new mxConnectionConstraint(new mxPoint(1, 0), true),
        new mxConnectionConstraint(new mxPoint(0, 0.15), true),
        new mxConnectionConstraint(new mxPoint(0, 0.25), true),
        new mxConnectionConstraint(new mxPoint(0, 0.35), true),
        new mxConnectionConstraint(new mxPoint(0, 0.45), true),
        new mxConnectionConstraint(new mxPoint(0, 0.55), true),
        new mxConnectionConstraint(new mxPoint(0, 0.65), true),
        new mxConnectionConstraint(new mxPoint(0, 0.75), true),
        new mxConnectionConstraint(new mxPoint(0, 0.85), true),
        new mxConnectionConstraint(new mxPoint(0, 0.95), true),
        new mxConnectionConstraint(new mxPoint(0, 0.05), true),
        new mxConnectionConstraint(new mxPoint(0, 0.15), true),
        new mxConnectionConstraint(new mxPoint(0, 0.25), true),
        new mxConnectionConstraint(new mxPoint(0, 0.35), true),
        new mxConnectionConstraint(new mxPoint(0, 0.45), true),
        new mxConnectionConstraint(new mxPoint(0, 0.55), true),
        new mxConnectionConstraint(new mxPoint(0, 0.65), true),
        new mxConnectionConstraint(new mxPoint(0, 0.75), true),
        new mxConnectionConstraint(new mxPoint(0, 0.85), true),
        new mxConnectionConstraint(new mxPoint(1, 0.15), true),
        new mxConnectionConstraint(new mxPoint(1, 0.25), true),
        new mxConnectionConstraint(new mxPoint(1, 0.35), true),
        new mxConnectionConstraint(new mxPoint(1, 0.45), true),
        new mxConnectionConstraint(new mxPoint(1, 0.55), true),
        new mxConnectionConstraint(new mxPoint(1, 0.65), true),
        new mxConnectionConstraint(new mxPoint(1, 0.75), true),
        new mxConnectionConstraint(new mxPoint(1, 0.85), true),
        new mxConnectionConstraint(new mxPoint(1, 0.95), true),
        new mxConnectionConstraint(new mxPoint(1, 0.05), true),
        new mxConnectionConstraint(new mxPoint(1, 0.15), true),
        new mxConnectionConstraint(new mxPoint(1, 0.25), true),
        new mxConnectionConstraint(new mxPoint(1, 0.35), true),
        new mxConnectionConstraint(new mxPoint(1, 0.45), true),
        new mxConnectionConstraint(new mxPoint(1, 0.55), true),
        new mxConnectionConstraint(new mxPoint(1, 0.65), true),
        new mxConnectionConstraint(new mxPoint(1, 0.75), true),
        new mxConnectionConstraint(new mxPoint(1, 0.85), true),
        new mxConnectionConstraint(new mxPoint(0, 1), true),
        new mxConnectionConstraint(new mxPoint(0.15, 1), true),
        new mxConnectionConstraint(new mxPoint(0.25, 1), true),
        new mxConnectionConstraint(new mxPoint(0.35, 1), true),
        new mxConnectionConstraint(new mxPoint(0.45, 1), true),
        new mxConnectionConstraint(new mxPoint(0.55, 1), true),
        new mxConnectionConstraint(new mxPoint(0.65, 1), true),
        new mxConnectionConstraint(new mxPoint(0.75, 1), true),
        new mxConnectionConstraint(new mxPoint(0.85, 1), true),
        new mxConnectionConstraint(new mxPoint(0.95, 1), true),
        new mxConnectionConstraint(new mxPoint(0.05, 1), true),
        new mxConnectionConstraint(new mxPoint(0.15, 1), true),
        new mxConnectionConstraint(new mxPoint(0.25, 1), true),
        new mxConnectionConstraint(new mxPoint(0.35, 1), true),
        new mxConnectionConstraint(new mxPoint(0.45, 1), true),
        new mxConnectionConstraint(new mxPoint(0.55, 1), true),
        new mxConnectionConstraint(new mxPoint(0.65, 1), true),
        new mxConnectionConstraint(new mxPoint(0.75, 1), true),
        new mxConnectionConstraint(new mxPoint(0.85, 1), true),
        new mxConnectionConstraint(new mxPoint(1, 1), true)];
    mxEllipse.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0), true), new mxConnectionConstraint(new mxPoint(1, 0), true),
        new mxConnectionConstraint(new mxPoint(0, 1), true), new mxConnectionConstraint(new mxPoint(1, 1), true),
        new mxConnectionConstraint(new mxPoint(0.5, 0), true), new mxConnectionConstraint(new mxPoint(0.5, 1), true),
        new mxConnectionConstraint(new mxPoint(0, 0.5), true), new mxConnectionConstraint(new mxPoint(1, 0.5))];
    PartialRectangleShape.prototype.constraints = mxRectangleShape.prototype.constraints;
    mxImageShape.prototype.constraints = mxRectangleShape.prototype.constraints;
    mxSwimlane.prototype.constraints = mxRectangleShape.prototype.constraints;
    PlusShape.prototype.constraints = mxRectangleShape.prototype.constraints;
    mxLabel.prototype.constraints = mxRectangleShape.prototype.constraints;

    NoteShape.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var s = Math.max(0, Math.min(w, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))));

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - s) * 0.5, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - s, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - s * 0.5, s * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, s));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, (h + s) * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 1), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 1), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 1), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false));

        if (w >= s * 2) {
            constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
        }

        return (constr);
    };

    CardShape.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var s = Math.max(0, Math.min(w, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))));

        constr.push(new mxConnectionConstraint(new mxPoint(1, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w + s) * 0.5, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, s, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, s * 0.5, s * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, s));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, (h + s) * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 1), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 1), false));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 1), false));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));

        if (w >= s * 2) {
            constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
        }

        return (constr);
    };

    CubeShape.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var s = Math.max(0, Math.min(w, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size)))));

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - s) * 0.5, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - s, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - s * 0.5, s * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, s));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, (h + s) * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 1), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w + s) * 0.5, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, s, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, s * 0.5, h - s * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h - s));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, (h - s) * 0.5));

        return (constr);
    };

    CylinderShape3.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var s = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'size', this.size))));

        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 1), false));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, s));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0), false, null, 0, s));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 1), false, null, 0, -s));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 1), false, null, 0, -s));

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, s + (h * 0.5 - s) * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0), false, null, 0, s + (h * 0.5 - s) * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0), false, null, 0, h - s - (h * 0.5 - s) * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h - s - (h * 0.5 - s) * 0.5));

        constr.push(new mxConnectionConstraint(new mxPoint(0.145, 0), false, null, 0, s * 0.29));
        constr.push(new mxConnectionConstraint(new mxPoint(0.855, 0), false, null, 0, s * 0.29));
        constr.push(new mxConnectionConstraint(new mxPoint(0.855, 1), false, null, 0, -s * 0.29));
        constr.push(new mxConnectionConstraint(new mxPoint(0.145, 1), false, null, 0, -s * 0.29));

        return (constr);
    };

    FolderShape.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'tabWidth', this.tabWidth))));
        var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'tabHeight', this.tabHeight))));
        var tp = mxUtils.getValue(this.style, 'tabPosition', this.tabPosition);

        if (tp == 'left') {
            constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false));
            constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx * 0.5, 0));
            constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, 0));
            constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, dy));
            constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w + dx) * 0.5, dy));
        } else {
            constr.push(new mxConnectionConstraint(new mxPoint(1, 0), false));
            constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx * 0.5, 0));
            constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, 0));
            constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, dy));
            constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx) * 0.5, dy));
        }

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, (h - dy) * 0.25 + dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, (h - dy) * 0.5 + dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, (h - dy) * 0.75 + dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, (h - dy) * 0.25 + dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, (h - dy) * 0.5 + dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, (h - dy) * 0.75 + dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0.25, 1), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 1), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0.75, 1), false));

        return (constr);
    }

    InternalStorageShape.prototype.constraints = mxRectangleShape.prototype.constraints;
    DataStorageShape.prototype.constraints = mxRectangleShape.prototype.constraints;
    TapeDataShape.prototype.constraints = mxEllipse.prototype.constraints;
    OrEllipseShape.prototype.constraints = mxEllipse.prototype.constraints;
    SumEllipseShape.prototype.constraints = mxEllipse.prototype.constraints;
    LineEllipseShape.prototype.constraints = mxEllipse.prototype.constraints;
    ManualInputShape.prototype.constraints = mxRectangleShape.prototype.constraints;
    DelayShape.prototype.constraints = mxRectangleShape.prototype.constraints;

    DisplayShape.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var dx = Math.min(w, h / 2);
        var s = Math.min(w - dx, Math.max(0, parseFloat(mxUtils.getValue(this.style, 'size', this.size))) * w);

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false, null));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, s, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (s + w - dx) * 0.5, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false, null));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - dx, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (s + w - dx) * 0.5, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, s, h));

        return (constr);
    };

    ModuleShape.prototype.getConstraints = function (style, w, h) {
        var x0 = parseFloat(mxUtils.getValue(style, 'jettyWidth', ModuleShape.prototype.jettyWidth)) / 2;
        var dy = parseFloat(mxUtils.getValue(style, 'jettyHeight', ModuleShape.prototype.jettyHeight));
        var constr = [new mxConnectionConstraint(new mxPoint(0, 0), false, null, x0),
            new mxConnectionConstraint(new mxPoint(0.25, 0), true),
            new mxConnectionConstraint(new mxPoint(0.5, 0), true),
            new mxConnectionConstraint(new mxPoint(0.75, 0), true),
            new mxConnectionConstraint(new mxPoint(1, 0), true),
            new mxConnectionConstraint(new mxPoint(1, 0.25), true),
            new mxConnectionConstraint(new mxPoint(1, 0.5), true),
            new mxConnectionConstraint(new mxPoint(1, 0.75), true),
            new mxConnectionConstraint(new mxPoint(0, 1), false, null, x0),
            new mxConnectionConstraint(new mxPoint(0.25, 1), true),
            new mxConnectionConstraint(new mxPoint(0.5, 1), true),
            new mxConnectionConstraint(new mxPoint(0.75, 1), true),
            new mxConnectionConstraint(new mxPoint(1, 1), true),
            new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, Math.min(h - 0.5 * dy, 1.5 * dy)),
            new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, Math.min(h - 0.5 * dy, 3.5 * dy))];

        if (h > 5 * dy) {
            constr.push(new mxConnectionConstraint(new mxPoint(0, 0.75), false, null, x0));
        }

        if (h > 8 * dy) {
            constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false, null, x0));
        }

        if (h > 15 * dy) {
            constr.push(new mxConnectionConstraint(new mxPoint(0, 0.25), false, null, x0));
        }

        return constr;
    };

    LoopLimitShape.prototype.constraints = mxRectangleShape.prototype.constraints;
    OffPageConnectorShape.prototype.constraints = mxRectangleShape.prototype.constraints;
    mxCylinder.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.15, 0.05), false),
        new mxConnectionConstraint(new mxPoint(0.5, 0), true),
        new mxConnectionConstraint(new mxPoint(0.85, 0.05), false),
        new mxConnectionConstraint(new mxPoint(0, 0.3), true),
        new mxConnectionConstraint(new mxPoint(0, 0.5), true),
        new mxConnectionConstraint(new mxPoint(0, 0.7), true),
        new mxConnectionConstraint(new mxPoint(1, 0.3), true),
        new mxConnectionConstraint(new mxPoint(1, 0.5), true),
        new mxConnectionConstraint(new mxPoint(1, 0.7), true),
        new mxConnectionConstraint(new mxPoint(0.15, 0.95), false),
        new mxConnectionConstraint(new mxPoint(0.5, 1), true),
        new mxConnectionConstraint(new mxPoint(0.85, 0.95), false)];
    UmlActorShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.25, 0.1), false),
        new mxConnectionConstraint(new mxPoint(0.5, 0), false),
        new mxConnectionConstraint(new mxPoint(0.75, 0.1), false),
        new mxConnectionConstraint(new mxPoint(0, 1 / 3), false),
        new mxConnectionConstraint(new mxPoint(0, 1), false),
        new mxConnectionConstraint(new mxPoint(1, 1 / 3), false),
        new mxConnectionConstraint(new mxPoint(1, 1), false),
        new mxConnectionConstraint(new mxPoint(0.5, 0.5), false)];
    ComponentShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.25, 0), true),
        new mxConnectionConstraint(new mxPoint(0.5, 0), true),
        new mxConnectionConstraint(new mxPoint(0.75, 0), true),
        new mxConnectionConstraint(new mxPoint(0, 0.3), true),
        new mxConnectionConstraint(new mxPoint(0, 0.7), true),
        new mxConnectionConstraint(new mxPoint(1, 0.25), true),
        new mxConnectionConstraint(new mxPoint(1, 0.5), true),
        new mxConnectionConstraint(new mxPoint(1, 0.75), true),
        new mxConnectionConstraint(new mxPoint(0.25, 1), true),
        new mxConnectionConstraint(new mxPoint(0.5, 1), true),
        new mxConnectionConstraint(new mxPoint(0.75, 1), true)];
    mxActor.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.5, 0), true),
        new mxConnectionConstraint(new mxPoint(0.25, 0.2), false),
        new mxConnectionConstraint(new mxPoint(0.1, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0, 0.75), true),
        new mxConnectionConstraint(new mxPoint(0.75, 0.25), false),
        new mxConnectionConstraint(new mxPoint(0.9, 0.5), false),
        new mxConnectionConstraint(new mxPoint(1, 0.75), true),
        new mxConnectionConstraint(new mxPoint(0.25, 1), true),
        new mxConnectionConstraint(new mxPoint(0.5, 1), true),
        new mxConnectionConstraint(new mxPoint(0.75, 1), true)];
    SwitchShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0), false),
        new mxConnectionConstraint(new mxPoint(0.5, 0.25), false),
        new mxConnectionConstraint(new mxPoint(1, 0), false),
        new mxConnectionConstraint(new mxPoint(0.25, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0.75, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0, 1), false),
        new mxConnectionConstraint(new mxPoint(0.5, 0.75), false),
        new mxConnectionConstraint(new mxPoint(1, 1), false)];
    TapeShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0.35), false),
        new mxConnectionConstraint(new mxPoint(0, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0, 0.65), false),
        new mxConnectionConstraint(new mxPoint(1, 0.35), false),
        new mxConnectionConstraint(new mxPoint(1, 0.5), false),
        new mxConnectionConstraint(new mxPoint(1, 0.65), false),
        new mxConnectionConstraint(new mxPoint(0.25, 1), false),
        new mxConnectionConstraint(new mxPoint(0.75, 0), false)];
    StepShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.25, 0), true),
        new mxConnectionConstraint(new mxPoint(0.5, 0), true),
        new mxConnectionConstraint(new mxPoint(0.75, 0), true),
        new mxConnectionConstraint(new mxPoint(0.25, 1), true),
        new mxConnectionConstraint(new mxPoint(0.5, 1), true),
        new mxConnectionConstraint(new mxPoint(0.75, 1), true),
        new mxConnectionConstraint(new mxPoint(0, 0.25), true),
        new mxConnectionConstraint(new mxPoint(0, 0.5), true),
        new mxConnectionConstraint(new mxPoint(0, 0.75), true),
        new mxConnectionConstraint(new mxPoint(1, 0.25), true),
        new mxConnectionConstraint(new mxPoint(1, 0.5), true),
        new mxConnectionConstraint(new mxPoint(1, 0.75), true)];
    mxLine.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0.25, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0.75, 0.5), false),
        new mxConnectionConstraint(new mxPoint(1, 0.5), false)];
    LollipopShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.5, 0), false),
        new mxConnectionConstraint(new mxPoint(0.5, 1), false)];
    mxDoubleEllipse.prototype.constraints = mxEllipse.prototype.constraints;
    mxRhombus.prototype.constraints = mxEllipse.prototype.constraints;
    mxTriangle.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0.25), true),
        new mxConnectionConstraint(new mxPoint(0, 0.5), true),
        new mxConnectionConstraint(new mxPoint(0, 0.75), true),
        new mxConnectionConstraint(new mxPoint(0.5, 0), true),
        new mxConnectionConstraint(new mxPoint(0.5, 1), true),
        new mxConnectionConstraint(new mxPoint(1, 0.5), true)];
    mxHexagon.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.375, 0), true),
        new mxConnectionConstraint(new mxPoint(0.5, 0), true),
        new mxConnectionConstraint(new mxPoint(0.625, 0), true),
        new mxConnectionConstraint(new mxPoint(0, 0.25), true),
        new mxConnectionConstraint(new mxPoint(0, 0.5), true),
        new mxConnectionConstraint(new mxPoint(0, 0.75), true),
        new mxConnectionConstraint(new mxPoint(1, 0.25), true),
        new mxConnectionConstraint(new mxPoint(1, 0.5), true),
        new mxConnectionConstraint(new mxPoint(1, 0.75), true),
        new mxConnectionConstraint(new mxPoint(0.375, 1), true),
        new mxConnectionConstraint(new mxPoint(0.5, 1), true),
        new mxConnectionConstraint(new mxPoint(0.625, 1), true)];
    mxCloud.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.25, 0.25), false),
        new mxConnectionConstraint(new mxPoint(0.4, 0.1), false),
        new mxConnectionConstraint(new mxPoint(0.16, 0.55), false),
        new mxConnectionConstraint(new mxPoint(0.07, 0.4), false),
        new mxConnectionConstraint(new mxPoint(0.31, 0.8), false),
        new mxConnectionConstraint(new mxPoint(0.13, 0.77), false),
        new mxConnectionConstraint(new mxPoint(0.8, 0.8), false),
        new mxConnectionConstraint(new mxPoint(0.55, 0.95), false),
        new mxConnectionConstraint(new mxPoint(0.875, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0.96, 0.7), false),
        new mxConnectionConstraint(new mxPoint(0.625, 0.2), false),
        new mxConnectionConstraint(new mxPoint(0.88, 0.25), false)];
    ParallelogramShape.prototype.constraints = mxRectangleShape.prototype.constraints;
    TrapezoidShape.prototype.constraints = mxRectangleShape.prototype.constraints;
    DocumentShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.25, 0), true),
        new mxConnectionConstraint(new mxPoint(0.5, 0), true),
        new mxConnectionConstraint(new mxPoint(0.75, 0), true),
        new mxConnectionConstraint(new mxPoint(0, 0.25), true),
        new mxConnectionConstraint(new mxPoint(0, 0.5), true),
        new mxConnectionConstraint(new mxPoint(0, 0.75), true),
        new mxConnectionConstraint(new mxPoint(1, 0.25), true),
        new mxConnectionConstraint(new mxPoint(1, 0.5), true),
        new mxConnectionConstraint(new mxPoint(1, 0.75), true)];
    mxArrow.prototype.constraints = null;

    TeeShape.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
        var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
        var w2 = Math.abs(w - dx) / 2;

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, dy * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.75 + dx * 0.25, dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w + dx) * 0.5, dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w + dx) * 0.5, (h + dy) * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w + dx) * 0.5, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 1), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx) * 0.5, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx) * 0.5, (h + dy) * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - dx) * 0.5, dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.25 - dx * 0.25, dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, dy * 0.5));

        return (constr);
    };

    CornerShape.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var dx = Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
        var dy = Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, dy * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w + dx) * 0.5, dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, dy));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, (h + dy) * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, dx * 0.5, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 1), false));

        return (constr);
    };

    CrossbarShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0), false),
        new mxConnectionConstraint(new mxPoint(0, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0, 1), false),
        new mxConnectionConstraint(new mxPoint(0.25, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0.5, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0.75, 0.5), false),
        new mxConnectionConstraint(new mxPoint(1, 0), false),
        new mxConnectionConstraint(new mxPoint(1, 0.5), false),
        new mxConnectionConstraint(new mxPoint(1, 1), false)];

    SingleArrowShape.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var aw = h * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'arrowWidth', this.arrowWidth))));
        var as = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'arrowSize', this.arrowSize))));
        var at = (h - aw) / 2;
        var ab = at + aw;

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, at));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - as) * 0.5, at));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - as, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - as, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w - as) * 0.5, h - at));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, h - at));

        return (constr);
    };

    DoubleArrowShape.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var aw = h * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'arrowWidth', SingleArrowShape.prototype.arrowWidth))));
        var as = w * Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.style, 'arrowSize', SingleArrowShape.prototype.arrowSize))));
        var at = (h - aw) / 2;
        var ab = at + aw;

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, as, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5, at));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - as, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w - as, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w * 0.5, h - at));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, as, h));

        return (constr);
    };

    CrossShape.prototype.getConstraints = function (style, w, h) {
        var constr = [];
        var m = Math.min(h, w);
        var size = Math.max(0, Math.min(m, m * parseFloat(mxUtils.getValue(this.style, 'size', this.size))));
        var t = (h - size) / 2;
        var b = t + size;
        var l = (w - size) / 2;
        var r = l + size;

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, l, t * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, l, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, r, 0));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, r, t * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, r, t));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, l, h - t * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, l, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 1), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, r, h));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, r, h - t * 0.5));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, r, b));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w + r) * 0.5, t));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, t));
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, w, b));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, (w + r) * 0.5, b));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, l, b));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, l * 0.5, t));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, t));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, 0, b));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, l * 0.5, b));
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false, null, l, t));

        return (constr);
    };

    //**********************************************************************************************************************************************************
//Accept Event Action
//**********************************************************************************************************************************************************
    /**
     * Extends mxShape.
     */
    function mxShapeSysMLAcceptEventAction(bounds, fill, stroke, strokewidth)
    {
        mxShape.call(this);
        this.bounds = bounds;
        this.fill = fill;
        this.stroke = stroke;
        this.strokewidth = (strokewidth != null) ? strokewidth : 1;
    };

    /**
     * Extends mxShape.
     */
    mxUtils.extend(mxShapeSysMLAcceptEventAction, mxShape);

    mxShapeSysMLAcceptEventAction.prototype.cst = {
        ACC_EVENT : 'mxgraph.sysml.accEvent'
    };

    /**
     * Function: paintVertexShape
     *
     * Paints the vertex shape.
     */
    mxShapeSysMLAcceptEventAction.prototype.paintVertexShape = function(c, x, y, w, h)
    {
        c.begin();
        c.moveTo(x, y);
        c.lineTo(x + w, y);
        c.lineTo(x + w, y + h);
        c.lineTo(x, y + h);
        c.lineTo(x + h * 0.3, y + h * 0.5);
        c.close();
        c.fillAndStroke();
    };

    mxCellRenderer.registerShape(mxShapeSysMLAcceptEventAction.prototype.cst.ACC_EVENT, mxShapeSysMLAcceptEventAction);

    mxShapeSysMLAcceptEventAction.prototype.getConstraints = function(style, w, h)
    {
        var constr = [];

        constr.push(new mxConnectionConstraint(new mxPoint(0, 0), false));
        constr.push(new mxConnectionConstraint(new mxPoint(0.1, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.2, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.3, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.4, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.6, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.7, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.8, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.9, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.05, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.15, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.25, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.35, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.45, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.55, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.65, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.75, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.85, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.2), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.3), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.4), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.6), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.7), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.8), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.9), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.05), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.15), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.25), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.35), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.45), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.55), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.65), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.75), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.85), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.2), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.3), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.4), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.5), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.6), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.7), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.8), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.9), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.05), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.15), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.25), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.35), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.45), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.55), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.65), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.75), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.85), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.1, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.2, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.3, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.4, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.5, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.6, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.7, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.8, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.9, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.05, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.15, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.25, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.35, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.45, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.55, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.65, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.75, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.85, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.15, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.25, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.35, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.45, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.55, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.65, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.75, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.85, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.95, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.05, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.15, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.25, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.35, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.45, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.55, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.65, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.75, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.85, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.15), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.25), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.35), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.45), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.55), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.65), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.75), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.85), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.95), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.05), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.15), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.25), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.35), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.45), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.55), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.65), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.75), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.85), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.15), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.25), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.35), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.45), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.55), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.65), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.75), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.85), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.95), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.05), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.15), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.25), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.35), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.45), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.55), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.65), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.75), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(1, 0.85), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.15, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.25, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.35, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.45, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.55, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.65, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.75, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.85, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.95, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.05, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.15, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.25, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.35, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.45, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.55, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.65, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.75, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0.85, 1), true)),
        constr.push(new mxConnectionConstraint(new mxPoint(0, 0.5), false, null,  h * 0.3, 0));

        return (constr);
    };
    UmlLifeline.prototype.getConstraints = function (style, w, h) {
        h = Math.ceil(h)
        return new Array(h).fill(0).map((_, index) => {
          return new mxConnectionConstraint(new mxPoint(0.5, index/h), true, null, 0)
        })
    }
    // UmlLifeline.prototype.constraints = [
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.001), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.002), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.003), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.004), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.005), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.006), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.007), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.008), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.009), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.01), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.011), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.012), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.013), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.014), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.015), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.016), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.017), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.018), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.019), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.02), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.021), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.022), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.023), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.024), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.025), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.026), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.027), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.028), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.029), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.03), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.031), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.032), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.033), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.034), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.035), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.036), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.037), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.038), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.039), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.04), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.041), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.042), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.043), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.044), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.045), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.046), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.047), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.048), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.049), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.05), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.051), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.052), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.053), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.054), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.055), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.056), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.057), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.058), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.059), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.06), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.061), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.062), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.063), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.064), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.065), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.066), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.067), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.068), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.069), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.07), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.071), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.072), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.073), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.074), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.075), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.076), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.077), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.078), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.079), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.08), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.081), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.082), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.083), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.084), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.085), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.086), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.087), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.088), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.089), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.09), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.091), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.092), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.093), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.094), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.095), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.096), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.097), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.098), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.099), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.100), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.101), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.102), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.103), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.104), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.105), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.106), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.107), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.108), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.109), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.11), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.111), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.112), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.113), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.114), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.115), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.116), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.117), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.118), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.119), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.12), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.121), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.122), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.123), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.124), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.125), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.126), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.127), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.128), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.129), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.13), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.131), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.132), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.133), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.134), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.135), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.136), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.137), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.138), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.139), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.14), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.141), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.142), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.143), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.144), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.145), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.146), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.147), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.148), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.149), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.15), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.151), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.152), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.153), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.154), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.155), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.156), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.157), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.158), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.159), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.16), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.161), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.162), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.163), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.164), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.165), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.166), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.167), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.168), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.169), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.17), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.171), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.172), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.173), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.174), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.175), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.176), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.177), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.178), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.179), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.18), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.181), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.182), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.183), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.184), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.185), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.186), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.187), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.188), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.189), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.19), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.191), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.192), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.193), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.194), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.195), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.196), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.197), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.198), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.199), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.2), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.201), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.202), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.203), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.204), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.205), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.206), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.207), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.208), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.209), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.21), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.211), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.212), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.213), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.214), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.215), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.216), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.217), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.218), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.219), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.22), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.221), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.222), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.223), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.224), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.225), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.226), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.227), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.228), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.229), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.23), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.231), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.232), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.233), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.234), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.235), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.236), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.237), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.238), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.239), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.24), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.241), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.242), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.243), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.244), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.245), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.246), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.247), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.248), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.249), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.25), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.251), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.252), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.253), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.254), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.255), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.256), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.257), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.258), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.259), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.26), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.261), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.262), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.263), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.264), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.265), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.266), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.267), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.268), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.269), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.27), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.271), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.272), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.273), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.274), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.275), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.276), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.277), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.278), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.279), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.28), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.281), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.282), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.283), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.284), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.285), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.286), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.287), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.288), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.289), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.29), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.291), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.292), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.293), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.294), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.295), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.296), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.297), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.298), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.299), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.3), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.301), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.302), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.303), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.304), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.305), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.306), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.307), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.308), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.309), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.31), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.311), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.312), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.313), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.314), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.315), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.316), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.317), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.318), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.319), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.32), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.321), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.322), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.323), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.324), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.325), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.326), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.327), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.328), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.329), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.33), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.331), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.332), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.333), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.334), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.335), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.336), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.337), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.338), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.339), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.34), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.341), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.342), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.343), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.344), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.345), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.346), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.347), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.348), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.349), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.35), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.351), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.352), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.353), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.354), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.355), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.356), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.357), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.358), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.359), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.36), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.361), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.362), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.363), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.364), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.365), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.366), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.367), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.368), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.369), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.37), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.371), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.372), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.373), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.374), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.375), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.376), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.377), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.378), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.379), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.38), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.381), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.382), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.383), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.384), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.385), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.386), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.387), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.388), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.389), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.39), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.391), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.392), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.393), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.394), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.395), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.396), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.397), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.398), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.399), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.4), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.401), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.402), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.403), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.404), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.405), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.406), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.407), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.408), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.409), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.41), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.411), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.412), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.413), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.414), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.415), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.416), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.417), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.418), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.419), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.42), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.421), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.422), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.423), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.424), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.425), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.426), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.427), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.428), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.429), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.43), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.431), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.432), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.433), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.434), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.435), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.436), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.437), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.438), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.439), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.44), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.441), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.442), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.443), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.444), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.445), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.446), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.447), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.448), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.449), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.45), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.451), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.452), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.453), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.454), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.455), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.456), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.457), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.458), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.459), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.46), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.461), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.462), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.463), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.464), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.465), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.466), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.467), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.468), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.469), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.47), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.471), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.472), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.473), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.474), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.475), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.476), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.477), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.478), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.479), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.48), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.481), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.482), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.483), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.484), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.485), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.486), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.487), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.488), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.489), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.49), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.491), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.492), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.493), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.494), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.495), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.496), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.497), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.498), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.499), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.5), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.501), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.502), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.503), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.504), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.505), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.506), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.507), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.508), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.509), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.51), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.511), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.512), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.513), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.514), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.515), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.516), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.517), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.518), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.519), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.52), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.521), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.522), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.523), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.524), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.525), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.526), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.527), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.528), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.529), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.53), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.531), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.532), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.533), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.534), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.535), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.536), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.537), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.538), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.539), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.54), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.541), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.542), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.543), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.544), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.545), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.546), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.547), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.548), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.549), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.55), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.551), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.552), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.553), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.554), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.555), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.556), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.557), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.558), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.559), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.56), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.561), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.562), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.563), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.564), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.565), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.566), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.567), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.568), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.569), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.57), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.571), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.572), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.573), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.574), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.575), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.576), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.577), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.578), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.579), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.58), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.581), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.582), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.583), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.584), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.585), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.586), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.587), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.588), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.589), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.59), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.591), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.592), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.593), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.594), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.595), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.596), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.597), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.598), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.599), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.6), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.601), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.602), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.603), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.604), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.605), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.606), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.607), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.608), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.609), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.61), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.611), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.612), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.613), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.614), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.615), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.616), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.617), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.618), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.619), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.62), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.621), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.622), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.623), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.624), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.625), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.626), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.627), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.628), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.629), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.63), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.631), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.632), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.633), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.634), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.635), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.636), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.637), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.638), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.639), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.64), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.641), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.642), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.643), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.644), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.645), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.646), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.647), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.648), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.649), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.65), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.651), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.652), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.653), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.654), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.655), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.656), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.657), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.658), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.659), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.66), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.661), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.662), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.663), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.664), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.665), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.666), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.667), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.668), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.669), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.67), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.671), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.672), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.673), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.674), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.675), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.676), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.677), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.678), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.679), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.68), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.681), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.682), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.683), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.684), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.685), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.686), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.687), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.688), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.689), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.69), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.691), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.692), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.693), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.694), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.695), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.696), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.697), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.698), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.699), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.7), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.701), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.702), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.703), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.704), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.705), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.706), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.707), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.708), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.709), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.71), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.711), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.712), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.713), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.714), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.715), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.716), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.717), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.718), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.719), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.72), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.721), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.722), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.723), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.724), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.725), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.726), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.727), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.728), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.729), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.73), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.731), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.732), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.733), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.734), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.735), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.736), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.737), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.738), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.739), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.74), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.741), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.742), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.743), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.744), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.745), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.746), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.747), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.748), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.749), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.75), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.751), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.752), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.753), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.754), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.755), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.756), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.757), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.758), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.759), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.76), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.761), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.762), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.763), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.764), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.765), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.766), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.767), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.768), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.769), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.77), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.771), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.772), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.773), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.774), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.775), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.776), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.777), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.778), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.779), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.78), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.781), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.782), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.783), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.784), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.785), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.786), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.787), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.788), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.789), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.79), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.791), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.792), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.793), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.794), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.795), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.796), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.797), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.798), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.799), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.8), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.801), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.802), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.803), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.804), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.805), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.806), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.807), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.808), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.809), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.81), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.811), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.812), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.813), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.814), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.815), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.816), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.817), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.818), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.819), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.82), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.821), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.822), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.823), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.824), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.825), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.826), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.827), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.828), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.829), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.83), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.831), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.832), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.833), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.834), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.835), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.836), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.837), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.838), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.839), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.84), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.841), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.842), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.843), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.844), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.845), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.846), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.847), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.848), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.849), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.85), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.851), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.852), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.853), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.854), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.855), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.856), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.857), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.858), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.859), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.86), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.861), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.862), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.863), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.864), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.865), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.866), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.867), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.868), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.869), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.87), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.871), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.872), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.873), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.874), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.875), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.876), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.877), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.878), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.879), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.88), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.881), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.882), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.883), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.884), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.885), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.886), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.887), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.888), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.889), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.89), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.891), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.892), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.893), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.894), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.895), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.896), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.897), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.898), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.899), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.9), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.901), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.902), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.903), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.904), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.905), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.906), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.907), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.908), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.909), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.91), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.911), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.912), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.913), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.914), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.915), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.916), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.917), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.918), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.919), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.92), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.921), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.922), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.923), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.924), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.925), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.926), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.927), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.928), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.929), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.93), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.931), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.932), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.933), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.934), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.935), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.936), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.937), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.938), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.939), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.94), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.941), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.942), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.943), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.944), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.945), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.946), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.947), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.948), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.949), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.95), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.951), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.952), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.953), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.954), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.955), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.956), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.957), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.958), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.959), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.96), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.961), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.962), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.963), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.964), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.965), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.966), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.967), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.968), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.969), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.97), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.971), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.972), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.973), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.974), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.975), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.976), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.977), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.978), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.979), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.98), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.981), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.982), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.983), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.984), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.985), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.986), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.987), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.988), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.989), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.99), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.991), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.992), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.993), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.994), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.995), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.996), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.997), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.998), false),
    //     new mxConnectionConstraint(new mxPoint(0.5, 0.999), false)
    // ];

    OrShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0.25), false),
        new mxConnectionConstraint(new mxPoint(0, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0, 0.75), false),
        new mxConnectionConstraint(new mxPoint(1, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0.7, 0.1), false),
        new mxConnectionConstraint(new mxPoint(0.7, 0.9), false)];
    XorShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0.175, 0.25), false),
        new mxConnectionConstraint(new mxPoint(0.25, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0.175, 0.75), false),
        new mxConnectionConstraint(new mxPoint(1, 0.5), false),
        new mxConnectionConstraint(new mxPoint(0.7, 0.1), false),
        new mxConnectionConstraint(new mxPoint(0.7, 0.9), false)];
    RequiredInterfaceShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0.5), false),
        new mxConnectionConstraint(new mxPoint(1, 0.5), false)];
    ProvidedRequiredInterfaceShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0.5), false),
        new mxConnectionConstraint(new mxPoint(1, 0.5), false)];
})();
